【问题标题】:react native search and scroll to hit反应原生搜索并滚动点击
【发布时间】:2018-05-26 02:37:46
【问题描述】:

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

尝试构建这个 sn-p 作为启动:

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

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

【问题讨论】:

    标签: reactjs typescript react-native react-animated


    【解决方案1】:

    我的猜测是:

    您可以从绑定ref&lt;ScrollView/&gt; 开始。

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

    以及您的每个&lt;Text/&gt; 组件(index)。

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

    然后您可以设置submit() function

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

    如果找到;可以使用measure() 检索目标xy 偏移量

    然后可以调用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)
      }
    
    }
    

    【讨论】:

    • 非常感谢您的回答。试过 www.snack.expo.io/@norfeldt/searching-and-scroll-to 但不能让它完全工作。有时它会滚动(到可见组件),但大多数情况下什么都没有发生..
    • 对我来说很好。你在输入numbers吗?
    【解决方案2】:

    步骤

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

    结果:

    【讨论】:

    • 非常感谢!您的示例也适用于不同高度的元素 - snack.expo.io/@norfeldt/search-and-scroll-to-hit
    • 是的,它旨在处理不同高度的行。它发生在 Facebook 帖子等一些内容上,无法避免将长/短的内容放在一起。它在我自己的应用程序中运行良好。
    【解决方案3】:

    首先,我强烈建议您使用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. 使用FlatList代替ScrollView,所以改成这样:

      <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还不是很熟悉,你需要知道,数据是在dataprop中作为一个数组添加的(我添加了一个100个数字的数组),它的渲染方式给出了FlatList as renderItemprop(我添加了与您相同样式的文本)。

    此外,请注意,您不需要将 ref 传递给 &lt;Text&gt;,因为 FlatList 已经知道它包含的项目。您只需要为FlatList 本身添加一个引用:

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

    现在当你想制作和滚动时,你可以简单地调用FlatListscrollToIndex方法,例如写一个名为scrollHandler的方法:

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

    请注意,flatListRef 是分配给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)}
    />
    

    【讨论】:

    • 您的回答非常好,并且对我的问题很准确。我的问题是我有不同高度的物品(知道我的例子没有)并且它不起作用 - 请参阅snack.expo.io/@norfeldt/searching-and-scroll-to
    • 我有几个担心的因素: 1- 为什么你的列表应该包含不同高度的项目?这是一个糟糕的 UX 设计实践,因为在智能手机的小屏幕上,用户通常不会期待这样的行为,它要么是特定卡片的列表,要么最好根本不列出。 2-如果您的列表包含不同高度的项目,最好不要使用scrollToIndex和scrollToItem,这两种方法的API仍然是实验性的,并且在复杂情况下有几个错误。我在讨论这个案例的帖子中添加了一个 PS。
    • 我知道使用不同的高度是不好的做法。但我正在解析一些需要以不同格式设置的 json 内容(并创建不同的高度)。
    • 试图再看一遍 FlatList(有性能问题),但阅读文档并不能帮助您处理动态内容facebook.github.io/react-native/docs/0.47/…
    猜你喜欢
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多