React Native - 如何在从另一个屏幕导航后将 ScrollView 滚动到给定位置
React Native - how to scroll a ScrollView to a given location after navigation from another screen
当我们刚刚通过 StackNavigator 导航到当前屏幕时,是否可以告诉 ScrollView 滚动到特定位置?
我有两个屏幕;菜单和项目。菜单是一个按钮列表,每个按钮对应一个项目。 Items 屏幕包含一个使用 ScrollView 构建的 Carousel,其中包含每个 Item 的图片和详细描述。
当我在“菜单”屏幕中单击一个按钮时,我想导航到“项目”屏幕,并自动滚动到该按钮所代表的项目。
我了解到您可以像这样使用 StackNavigator 时传入参数:但我不知道如何在我的项目屏幕中读出该参数。
navigate('Items', { id: '1' })
那么这在 React Native 中是可能的吗?我该怎么做?或者我用错了导航器?
这是我的两个屏幕的简化版本:
App.js:
const SimpleApp = StackNavigator({
Menu: { screen: MenuScreen},
Items: { screen: ItemScreen }
}
);
export default class App extends React.Component {
render() {
return <SimpleApp />;
}
}
Menu.js
export default class Menu extends React.Component {
constructor(props){
super(props)
this.seeDetail = this.seeDetail.bind(this)
}
seeDetail(){
const { navigate } = this.props.navigation;
navigate('Items')
}
render(){
<Button onPress={this.seeDetail} title='1'/>
<Button onPress={this.seeDetail} title='2'/>
}
}
Items.js
export default class Items extends React.Component {
render(){
let scrollItems = [] //Somecode that generates and array of items
return (
<View>
<View style={styles.scrollViewContainer}>
<ScrollView
horizontal
pagingEnabled
ref={(ref) => this.myScroll = ref}>
{scrollItems}
</ScrollView>
</View>
</View>
)
}
}
P.S 目前我特别针对 Android,但理想情况下可能会有一个跨平台的解决方案。
是的,这可以通过使用 scrollTo
方法实现 - 请参阅 docs。您可以在 componentDidMount
中调用此方法。你只需要一个 ref 来调用它:this.myScroll.scrollTo(...)
。请注意,如果您有一组相同类型的项目,则应改用 FlatList
。
I read that you can pass in parameters when using the StackNavigator like so: but I don't know how to read out that parameter in my Items screen.
这是通过在您的子组件中访问 this.props.navigation.state.params
来实现的。
我认为在滚动视图引用上调用 scrollTo
的最佳时间是它第一次被分配时。你已经给了它一个参考和 运行 一个回调函数 - 我只是调整它以便它也同时调用 scrollTo
:
export default class Items extends React.Component {
render(){
let scrollItems = [] //Somecode that generates and array of items
const {id} = this.props.navigation.state.params;
return (
<View>
<View style={styles.scrollViewContainer}>
<ScrollView
horizontal
pagingEnabled
ref={(ref) => {
this.myScroll = ref
this.myScroll.scrollTo() // !!
}>
{scrollItems}
</ScrollView>
</View>
</View>
)
}
}
这就是我使用更直观的 FlatLists or SectionLists (which inherit from VirtualizedList) instead of ScrollViews. VirtualizedList
has a scrollToIndex 函数的原因。 ScrollView 的 scrollTo 需要 x 和 y 参数,这意味着您必须计算要滚动到的确切位置——将每个滚动项目的宽度乘以您要滚动到的项目的索引。如果每个项目都涉及填充,那就更麻烦了。
这里是滚动到带有 id 的道具的例子。
import React, { Component } from 'react';
import { StyleSheet, Text, View, ScrollView, TouchableOpacity, Dimensions, Alert, findNodeHandle, Image } from 'react-native';
class MyCustomScrollToElement extends Component {
constructor(props) {
super(props)
this.state = {
}
this._nodes = new Map();
}
componentDidMount() {
const data = ['First Element', 'Second Element', 'Third Element', 'Fourth Element', 'Fifth Element' ];
data.filter((el, idx) => {
if(el===this.props.id){
this.scrollToElement(idx);
}
})
}
scrollToElement =(indexOf)=>{
const node = this._nodes.get(indexOf);
const position = findNodeHandle(node);
this.myScroll.scrollTo({ x: 0, y: position, animated: true });
}
render(){
const data = ['First Element', 'Second Element', 'Third Element', 'Fourth Element', 'Fifth Element' ];
return (
<View style={styles.container}>
<ScrollView ref={(ref) => this.myScroll = ref} style={[styles.container, {flex:0.9}]} keyboardShouldPersistTaps={'handled'}>
<View style={styles.container}>
{data.map((elm, idx) => <View ref={ref => this._nodes.set(idx, ref)} style={{styles.element}}><Text>{elm}</Text></View>)}
</View>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexGrow: 1,
backgroundColor:"#d7eff9"
},
element:{
width: 200,
height: 200,
backgroundColor: 'red'
}
});
export default MyCustomScrollToElement;
对于 iOS - 使用 ScrollView
的 contentOffset
属性 的最佳方式。通过这种方式,它将最初呈现在正确的位置。使用 scrollTo
将在第一个渲染之后添加额外的多余渲染。
对于 Android - 除了 scrollTo
别无选择
当我们刚刚通过 StackNavigator 导航到当前屏幕时,是否可以告诉 ScrollView 滚动到特定位置?
我有两个屏幕;菜单和项目。菜单是一个按钮列表,每个按钮对应一个项目。 Items 屏幕包含一个使用 ScrollView 构建的 Carousel,其中包含每个 Item 的图片和详细描述。
当我在“菜单”屏幕中单击一个按钮时,我想导航到“项目”屏幕,并自动滚动到该按钮所代表的项目。
我了解到您可以像这样使用 StackNavigator 时传入参数:但我不知道如何在我的项目屏幕中读出该参数。
navigate('Items', { id: '1' })
那么这在 React Native 中是可能的吗?我该怎么做?或者我用错了导航器?
这是我的两个屏幕的简化版本:
App.js:
const SimpleApp = StackNavigator({
Menu: { screen: MenuScreen},
Items: { screen: ItemScreen }
}
);
export default class App extends React.Component {
render() {
return <SimpleApp />;
}
}
Menu.js
export default class Menu extends React.Component {
constructor(props){
super(props)
this.seeDetail = this.seeDetail.bind(this)
}
seeDetail(){
const { navigate } = this.props.navigation;
navigate('Items')
}
render(){
<Button onPress={this.seeDetail} title='1'/>
<Button onPress={this.seeDetail} title='2'/>
}
}
Items.js
export default class Items extends React.Component {
render(){
let scrollItems = [] //Somecode that generates and array of items
return (
<View>
<View style={styles.scrollViewContainer}>
<ScrollView
horizontal
pagingEnabled
ref={(ref) => this.myScroll = ref}>
{scrollItems}
</ScrollView>
</View>
</View>
)
}
}
P.S 目前我特别针对 Android,但理想情况下可能会有一个跨平台的解决方案。
是的,这可以通过使用 scrollTo
方法实现 - 请参阅 docs。您可以在 componentDidMount
中调用此方法。你只需要一个 ref 来调用它:this.myScroll.scrollTo(...)
。请注意,如果您有一组相同类型的项目,则应改用 FlatList
。
I read that you can pass in parameters when using the StackNavigator like so: but I don't know how to read out that parameter in my Items screen.
这是通过在您的子组件中访问 this.props.navigation.state.params
来实现的。
我认为在滚动视图引用上调用 scrollTo
的最佳时间是它第一次被分配时。你已经给了它一个参考和 运行 一个回调函数 - 我只是调整它以便它也同时调用 scrollTo
:
export default class Items extends React.Component {
render(){
let scrollItems = [] //Somecode that generates and array of items
const {id} = this.props.navigation.state.params;
return (
<View>
<View style={styles.scrollViewContainer}>
<ScrollView
horizontal
pagingEnabled
ref={(ref) => {
this.myScroll = ref
this.myScroll.scrollTo() // !!
}>
{scrollItems}
</ScrollView>
</View>
</View>
)
}
}
这就是我使用更直观的 FlatLists or SectionLists (which inherit from VirtualizedList) instead of ScrollViews. VirtualizedList
has a scrollToIndex 函数的原因。 ScrollView 的 scrollTo 需要 x 和 y 参数,这意味着您必须计算要滚动到的确切位置——将每个滚动项目的宽度乘以您要滚动到的项目的索引。如果每个项目都涉及填充,那就更麻烦了。
这里是滚动到带有 id 的道具的例子。
import React, { Component } from 'react';
import { StyleSheet, Text, View, ScrollView, TouchableOpacity, Dimensions, Alert, findNodeHandle, Image } from 'react-native';
class MyCustomScrollToElement extends Component {
constructor(props) {
super(props)
this.state = {
}
this._nodes = new Map();
}
componentDidMount() {
const data = ['First Element', 'Second Element', 'Third Element', 'Fourth Element', 'Fifth Element' ];
data.filter((el, idx) => {
if(el===this.props.id){
this.scrollToElement(idx);
}
})
}
scrollToElement =(indexOf)=>{
const node = this._nodes.get(indexOf);
const position = findNodeHandle(node);
this.myScroll.scrollTo({ x: 0, y: position, animated: true });
}
render(){
const data = ['First Element', 'Second Element', 'Third Element', 'Fourth Element', 'Fifth Element' ];
return (
<View style={styles.container}>
<ScrollView ref={(ref) => this.myScroll = ref} style={[styles.container, {flex:0.9}]} keyboardShouldPersistTaps={'handled'}>
<View style={styles.container}>
{data.map((elm, idx) => <View ref={ref => this._nodes.set(idx, ref)} style={{styles.element}}><Text>{elm}</Text></View>)}
</View>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexGrow: 1,
backgroundColor:"#d7eff9"
},
element:{
width: 200,
height: 200,
backgroundColor: 'red'
}
});
export default MyCustomScrollToElement;
对于 iOS - 使用 ScrollView
的 contentOffset
属性 的最佳方式。通过这种方式,它将最初呈现在正确的位置。使用 scrollTo
将在第一个渲染之后添加额外的多余渲染。
对于 Android - 除了 scrollTo