问题
I am trying to use a horizontal ScrollView in React Native for Android, where the starting position is in the middle of the scrolling images rather than (0,0).
The scrollTo
method seems to be called correctly inside componentDidMount
but nothing moves in the application, it still shows as starting the scroll all the way to the left.
Since this is Android I don't have access to contentOffset props or I would set that directly, according to the documentation. Here is the code:
'use strict';
var React = require('react-native');
var {
StyleSheet,
View,
Text,
ScrollView,
Component,
} = React;
var precomputeStyle = require('precomputeStyle');
class Carousel extends Component {
constructor(props, context) {
super(props, context);
//this.changeContent = this.changeContent.bind(this);
}
componentDidMount() {
this.myScroll.scrollTo(100);
console.log("called DidMount");
}
render() {
return (
<View style={{flex: 1}}>
<ScrollView ref={(ref) => this.myScroll = ref}
contentContainerStyle={styles.container}
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
bounces={true}
onMomentumScrollEnd={this.onAnimationEnd}
>
{this.props.children}
</ScrollView>
</View>
);
}
onAnimationEnd(e) {
console.log("curr offset: " + e.nativeEvent.contentOffset.x);
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
page: {
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
},
});
module.exports = Carousel;
回答1:
I had the same issue, and wasted several hours no it:
1: in android, ScrollView can scroll only when its size < content's size
2: in react native android, if you call ScrollView.scrollTo() in componentDidMount, it won't work, because ScrollView has a layout animation when create, you can find it in ReactScrollView.java
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Call with the present values in order to re-layout if necessary
scrollTo(getScrollX(), getScrollY());
}
so, you must delay it after the animation
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this.myScroll.scrollTo(100);
console.log("called DidMount");
})
}
回答2:
This works on React Native 0.44.0. Thanks for the hint @Eldelshell. It also seems to work with any timeout value. At least on the emulator. I found that the answer involving InteractionManager.runAfterInteractions
did nothing to fix the issue but perhaps that's a difference in versions.
componentDidMount() {
setTimeout(() => {
this._scroll.scrollTo({y: 100})
}, 1)
}
回答3:
I wanted to avoid using delays and timers so after a bit of digging I found that using onLayout
works very smooth:
scrollToInitialPosition = () => {
this.scrollViewRef.scrollTo({ y: 100 });
}
...
<ScrollView
ref={(ref) => { this.scrollViewRef = ref; }}
onLayout={this.scrollToInitialPosition}
/>
回答4:
Thanks @David Nathan, using InteractionManager
works for me.
also note that unlike setTimeout
, runAfterInteractions
will not delay active animations.
From InteractionManager docs
来源:https://stackoverflow.com/questions/33208477/react-native-android-scrollview-scrollto-not-working