我正在尝试在Android中使用水平ScrollView in React Native ,其中起始位置位于滚动图像的中间而不是(0,0)。
scrollTo
方法似乎在componentDidMount
内被正确调用,但是在应用程序中没有任何移动,它仍然显示为向左开始滚动。
由于这是Android,我无法访问contentOffset道具,或者我会直接设置它,根据文档。这是代码:
'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;
答案 0 :(得分:37)
我有同样的问题,浪费了几个小时没有它:
1:在android中,ScrollView只能在其大小&lt;内容的大小
2:在本机android中,如果你在componentDidMount中调用ScrollView.scrollTo(),它将无法工作,因为ScrollView在创建时有一个布局动画,你可以在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());
}
所以,你必须在动画之后延迟它
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this.myScroll.scrollTo(100);
console.log("called DidMount");
})
}
答案 1 :(得分:14)
这适用于React Native 0.44.0。感谢@Eldelshell的提示。它似乎也适用于任何超时值。至少在模拟器上。我发现涉及InteractionManager.runAfterInteractions
的答案没有解决问题,但也许这是版本的差异。
componentDidMount() {
setTimeout(() => {
this._scroll.scrollTo({y: 100})
}, 1)
}
答案 2 :(得分:1)
我想避免使用延迟和计时器,因此,经过一番挖掘,我发现使用onLayout
的工作非常顺畅:
scrollToInitialPosition = () => {
this.scrollViewRef.scrollTo({ y: 100 });
}
...
<ScrollView
ref={(ref) => { this.scrollViewRef = ref; }}
onLayout={this.scrollToInitialPosition}
/>
答案 3 :(得分:0)
我认为应该有一个更现代的钩子版本:
const MyComponent = (props) => {
const componentRef = useRef(null)
// this is the same as useEffect but only runs after finishing rendering
useLayoutEffect(() => {
// unlike class examples, the actual ref is stored in the current property
scrollViewRef.current.scrollTo({ y: 100 })
// this empty because we don't care about any other variables,
// if you add other stuff into this function,
// you'll have to add any hook based variables into this array
}, [])
// ditto about current here:
return (
<ScrollView ref={(ref) => (componentRef.current = ref)}>
{...}
</ScrollView>)
}
答案 4 :(得分:-1)
感谢@David Nathan使用InteractionManager
对我有用。
还请注意,与setTimeout
不同,runAfterInteractions
不会延迟活动动画。