对本机搜索做出反应并滚动以点击
react native search and scroll to hit
我需要一些帮助来实现搜索和滚动以在 React Native 中点击。进行了大量搜索并最终陷入死胡同(找到了一些我无法开始工作的 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',
},
});
如能提供入门帮助,我们将不胜感激。
我的猜测是:
您可以先绑定 <ScrollView/>
的 ref
。
// 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
。
所述函数可以使用 try
catch
语句找到 ref
等于 this.state.text
的边缘情况下的优雅失败。
如果找到;可以使用 measure()
检索目标 x
和 y
偏移量
然后可以调用 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)
}
}
步骤
- 记住每个项目的位置
onLayout
。
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>
)
}
}
结果:
首先,我强烈建议您使用 FlatList
而不是 ScrollView
。这有几个原因:
FlatList
与 ScrollView 相比具有更优化的性能(在滚动视图中,所有项目都会立即呈现,无论它们是否在屏幕上可见)
- 此外,在
FlatList
中处理滚动和渲染项目要简单得多,您不需要了解任何有关 x、y 轴和像素的知识,您只需使用索引即可。
为了全面比较这两种方法,您可以查看:
http://matthewsessions.com/2017/05/15/optimizing-list-render-performance.html
回到你的问题,我说了我建议你使用FlatList,那么一切都会变得非常简单。
您可以在以下位置找到您的博览会的修改示例:
https://snack.expo.io/HkMZS1SGz
您需要在代码中进行的更改包括:
不使用 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
作为 renderItem
prop(我添加了与您相同样式的文本)。
此外,请注意您不需要将 ref 传递给 <Text>
,因为 FlatList
已经知道它包含的项目。您只需要向 FlatList
本身添加一个引用:
ref={ref => {this.flatListRef = ref;}}
现在当你想要制作和滚动时,你可以简单地调用FlatList
的scrollToIndex
方法,例如写一个方法叫做scrollHandler
:
// Scroll to Query
scrollHandler = (itemIndex)=>{
this.flatListRef.scrollToIndex({animated: true, index: itemIndex});
}
请注意,flatListRef
是分配给 FlatList
的 ref 的名称。
现在,当你想执行滚动动作时,你可以简单地调用这个方法。例如,将您的文本输入修改为:
<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)}
/>
我需要一些帮助来实现搜索和滚动以在 React Native 中点击。进行了大量搜索并最终陷入死胡同(找到了一些我无法开始工作的 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',
},
});
如能提供入门帮助,我们将不胜感激。
我的猜测是:
您可以先绑定 <ScrollView/>
的 ref
。
// 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
。
所述函数可以使用 try
catch
语句找到 ref
等于 this.state.text
的边缘情况下的优雅失败。
如果找到;可以使用 measure()
x
和 y
偏移量
然后可以调用 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)
}
}
步骤
- 记住每个项目的位置
onLayout
。 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>
)
}
}
结果:
首先,我强烈建议您使用 FlatList
而不是 ScrollView
。这有几个原因:
FlatList
与 ScrollView 相比具有更优化的性能(在滚动视图中,所有项目都会立即呈现,无论它们是否在屏幕上可见)- 此外,在
FlatList
中处理滚动和渲染项目要简单得多,您不需要了解任何有关 x、y 轴和像素的知识,您只需使用索引即可。
为了全面比较这两种方法,您可以查看:
http://matthewsessions.com/2017/05/15/optimizing-list-render-performance.html
回到你的问题,我说了我建议你使用FlatList,那么一切都会变得非常简单。 您可以在以下位置找到您的博览会的修改示例:
https://snack.expo.io/HkMZS1SGz
您需要在代码中进行的更改包括:
不使用 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
作为 renderItem
prop(我添加了与您相同样式的文本)。
此外,请注意您不需要将 ref 传递给 <Text>
,因为 FlatList
已经知道它包含的项目。您只需要向 FlatList
本身添加一个引用:
ref={ref => {this.flatListRef = ref;}}
现在当你想要制作和滚动时,你可以简单地调用FlatList
的scrollToIndex
方法,例如写一个方法叫做scrollHandler
:
// Scroll to Query
scrollHandler = (itemIndex)=>{
this.flatListRef.scrollToIndex({animated: true, index: itemIndex});
}
请注意,flatListRef
是分配给 FlatList
的 ref 的名称。
现在,当你想执行滚动动作时,你可以简单地调用这个方法。例如,将您的文本输入修改为:
<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)}
/>