Búsqueda de sitios web

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:

  1. FlatList tiene 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)
  2. 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:

  1. 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)}
/>

Artículos relacionados