StackNavigatorを使用して現在の画面に移動したときに、ScrollViewに特定の位置にスクロールするように指示することはできますか?
2つの画面があります。メニューとアイテム。メニューは、各項目に1つずつ、ボタンのリストです。アイテム画面には、ScrollViewを使用して構築されたカルーセルと、各アイテムの画像と詳細な説明が含まれています。
メニュー画面でボタンをクリックすると、アイテム画面に移動し、ボタンが表すアイテムまで自動的にスクロールします。
StackNavigatorを使用するときにパラメーターを渡すことができると読みましたが、[アイテム]画面でそのパラメーターを読み取る方法がわかりません。
navigate('Items', { id: '1' })
これはReact Nativeで可能なことであり、どのようにすればよいですか?または、おそらく間違ったナビゲーターを使用していますか?
これは、私の2つの画面の機能が低下したバージョンです。
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=をターゲットにしていますが、理想的にはクロスプラットフォームソリューションがある可能性があります。
StackNavigatorを使用するときにパラメーターを渡すことができると読みましたが、[アイテム]画面でそのパラメーターを読み取る方法がわかりません。
これは、子コンポーネント内のthis.props.navigation.state.params
にアクセスすることで実現されます。
Scrollview参照で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>
)
}
}
そして、これがScrollViewsの代わりに FlatLists または SectionLists ( VirtualizedList から継承)を使用する理由です。 VirtualizedList
には 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;
はい、これはscrollTo
メソッドを使用することで可能です- docs を参照してください。このメソッドはcomponentDidMount
で呼び出すことができます。 this.myScroll.scrollTo(...)
のように呼び出すには、参照が必要です。すべて同じタイプの項目の配列がある場合は、代わりにFlatList
を使用する必要があることに注意してください。
IOSの場合-ScrollView
のcontentOffset
プロパティを使用する最良の方法。このようにして、最初は正しい位置にレンダリングされます。 scrollTo
を使用すると、最初のレンダリングの後に余分なレンダリングが追加されます。
Androidの場合-scrollTo
以外のオプションはありません