reactjs - buscar en react native y desplazarse hasta el resultado
Necesito ayuda para implementar una búsqueda y desplazamiento para tocar en React Native. Hice muchas búsquedas y terminé en algunos callejones sin salida (encontré algunos ejemplos de refs que no pude hacer funcionar).
Intenté construir este fragmento como un punto de partida:
https://snack.expo.io/@norfeldt/searching-and-scroll-to
import React, { Component } from 'react';
import { Text, View, ScrollView, TextInput, StyleSheet } from 'react-native';
export default class App extends Component {
state = {
text: '41'
}
render() {
return (
<View style={styles.container}>
<TextInput
style={{height: 60, borderColor: 'gray', borderWidth: 1, borderRadius: 10, margin: 5, padding:30, color: 'black', }}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
<ScrollView >
{[...Array(100)].map((_, i) => {return <Text style={styles.paragraph} key={i}>{i}</Text>})}
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 10,
backgroundColor: '#ecf0f1',
},
paragraph: {
margin: 10,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
});
Cualquier ayuda para comenzar sería apreciada.
Respuesta #1
Mi suposición sería:
Podrías empezar vinculando un ref de tu <ScrollView/>.
// ScrollView Ref.
<ScrollView ref={(ref) => this['ScrollView'] = ref}>
...
</ScrollView>
Y cada uno de tus componentes <Text/> (por índice).
// Text Refs.
<Text ref={(ref) => this[i] = ref} style={styles.paragraph} key={i}>{i}</Text>
Entonces podrías establecer una función submit().
Dicha función podría encontrar el ref igual a this.state.text usando una sentencia try catch para un fallo controlado en casos límite.
Si se encuentra; el desplazamiento del objetivo x y y se puede recuperar usando measure()
Luego se podría llamar a scrollTo() para desplazarse al componente objetivo.
// Scroll To Query.
submit = () => {
try {
const { text } = this.state // Text.
const target = this[text] // Target.
// Locate Target.
target.measure((framex, framey, width, height, x, y) => {
// Scroll To Target.
this.ScrollView.scrollTo({x, y, animated: true})
})
} catch (error) {
return console.log(error)
}
}
Respuesta #2
En primer lugar, recomiendo encarecidamente que uses FlatList en lugar de ScrollView. Hay varias razones para esto:
FlatListtiene un rendimiento mucho más optimizado en comparación con ScrollView (en ScrollView todos los elementos se renderizan de una vez, independientemente de si son visibles en la pantalla o no)- Además, el manejo del desplazamiento y de los elementos renderizados es mucho más sencillo en
FlatList, no necesitas saber nada sobre los ejes x, y y los píxeles, solo trabajas con los índices.
para tener una comparación completa entre estos dos métodos, puedes mirar:
http://matthewsessions.com/2017/05/15/optimizing-list-render-performance.html
Ahora, volviendo a tu pregunta, como dije, te sugiero que uses FlatList, entonces todo será tan simple como un trozo de pastel. Puedes encontrar un ejemplo modificado de tu expo en:
https://snack.expo.io/HkMZS1SGz
Los cambios que necesitas hacer en tu código incluyen:
En lugar de usar ScrollView, usa FlatList, así que cambia esto:
<FlatList ref={ref => {this.flatListRef=ref;}} data={new Array(100).fill(0).map((item, index) => index)} renderItem={({ item }) => ( <Text style={styles.paragraph}> {item} </Text> )} />
Si aún no estás familiarizado con FlatList, necesitas saber que los datos se agregan en la propiedad data como un arreglo (agregué un arreglo de 100 números), y la forma en que se renderiza se da a FlatList como la propiedad renderItem (agregué el texto con el mismo estilo que tú hiciste).
Además, tenga en cuenta que no necesita pasar ref a <Text>, porque FlatList ya conoce los elementos que contiene. Solo necesita agregar un ref al FlatList en sí:
ref={ref => {this.flatListRef = ref;}}
Ahora, cada vez que quieras hacer un desplazamiento, puedes simplemente llamar al método scrollToIndex del FlatList, por ejemplo, escribe un método llamado scrollHandler:
// Scroll to Query
scrollHandler = (itemIndex)=>{
this.flatListRef.scrollToIndex({animated: true, index: itemIndex});
}
Solo presta atención a que,flatListRef es el nombre de la referencia asignada al FlatList.
ahora, cuando quieras realizar una acción de desplazamiento, simplemente puedes llamar a este método. Por ejemplo, modifica tu entrada de texto a:
<TextInput
style={{height: 60, borderColor: 'gray', borderWidth: 1,
borderRadius: 10, margin: 5, padding:30, color: 'black', }}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
onSubmitEditing={()=>this.scrollHandler(this.state.text)}
/>
