6

我需要一些帮助来实现搜索和滚动以响应本机。做了很多搜索,最终陷入了一些死胡同(找到了一些refs我无法工作的例子)。

尝试构建此代码段作为启动:

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',
  },
});

任何帮助入门将不胜感激。

4

3 回答 3

2

首先,我强烈建议您使用FlatList而不是ScrollView. 这有几个原因:

  1. FlatList与 ScrollView 相比具有更优化的性能(在滚动视图中,所有项目都会立即呈现,无论它们是否在屏幕上可见)
  2. 此外,处理滚动和渲染项目要简单得多FlatList,您不需要了解有关 x、y 轴和像素的任何信息,只需使用索引即可。

为了对这两种方法进行全面比较,您可以查看:

http://matthewsessions.com/2017/05/15/optimizing-list-render-performance.html

现在回到你的问题,正如我所说的,我建议你使用 FlatList,那么一切都会变得轻而易举。您可以在以下位置找到修改后的博览会示例:

https://snack.expo.io/HkMZS1SGz

您需要在代码中进行的更改包括:

  1. 而不是 ScrollView 使用,FlatList,所以改变这个:

    <FlatList ref={ref => {this.flatListRef = ref;}} data={new Array(100).fill(0).map((item, index) => index)} renderItem={({ item }) => ( <Text style={styles.paragraph}> {item} </Text> )} />

如果你还不熟悉FlatList,你需要知道,数据是data作为数组添加到 prop 中的(我添加了一个 100 个数字的数组),它的呈现方式是FlatList作为renderItemprop 给出的(我添加了带有与您相同的样式)。

此外,请注意您不需要将 ref 传递给<Text>,因为FlatList已经知道它包含的项目。您只需要向FlatList自身添加一个 ref:

 ref={ref => {this.flatListRef = ref;}}

现在,当您想要制作和滚动时,您可以简单地调用scrollToIndex的方法FlatList,例如编写一个名为的方法scrollHandler

 // Scroll to Query
  scrollHandler = (itemIndex)=>{
    this.flatListRef.scrollToIndex({animated: true, index: itemIndex});
  }

请注意,flatListRef是分配给 . 的 ref 的名称FlatList

现在,当你想要执行滚动动作时,你可以简单地调用这个方法。例如,将您的文本输入修改为:

<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)}
/>
于 2017-12-18T06:56:47.693 回答
2

我的猜测是:

你可以从绑定ref你的<ScrollView/>.

// ScrollView Ref.
<ScrollView ref={(ref) => this['ScrollView'] = ref}>
  ...
</ScrollView>

以及您的每个<Text/>组件(按index)。

// Text Refs.
<Text ref={(ref) => this[i] = ref} style={styles.paragraph} key={i}>{i}</Text>

然后你可以设置一个submit() function.

所述函数可以找到ref等于在边缘情况下this.state.text使用try catch优雅失败的语句。

如果找到;可以使用检索目标x和偏移量ymeasure()

scrollTo()然后可以调用以滚动到目标组件。

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

}
于 2017-12-17T12:55:33.950 回答
1

脚步

  1. 用 记住每个项目的位置onLayout
  2. scrollTo()文本输入时的位置,并且仅当找到项目时。

代码

const styles = StyleSheet.create({
    textinput: {
        borderBottomColor: 'purple',
        textAlign: 'center',
        borderBottomWidth: 2,
        height: 40,
        marginTop: 20,
    },
    text: {
        textAlign: 'center',
        fontSize: 16,
        margin: 10,
    } 
});



export class App extends Component {
    data = [];
    datapos = {};
    scrollref = null;
    constructor(props) {
        super(props);
        /// make 100s example data
        for (var i =0; i<100; ++i)
            this.data.push(i);

        this.state = {
            inputvalue: '0'
        }
    }

    render() {
        return (
            <View style={{flex: 1}}>
                <TextInput style={styles.textinput}
                    value={this.state.inputvalue}
                    onChangeText={(text) => {
                        this.setState({inputvalue: text});
                        let y = this.datapos[+text];
                        y !== undefined && this.scrollref.scrollTo({ y, animated: true });
                    }}
                />
                <ScrollView
                    ref={(ref) => this.scrollref = ref}
                    >
                    {
                        this.data.map( (data) => (
                            <Text style={styles.text}
                                key={data}
                                onLayout={(layout) => this.datapos[data] = layout.nativeEvent.layout.y}
                                >{data}</Text>
                        ))
                    }
                </ScrollView>
            </View>
        )
    }
}

结果:

在此处输入图像描述

于 2017-12-18T03:15:20.950 回答