反应本机 Android ScrollView scrollTo 不工作
React native Android ScrollView scrollTo not working
我正在尝试在 React Native 中为 Android 使用 水平滚动视图,其中起始位置在滚动图像的中间而不是 (0, 0).
似乎在 componentDidMount
中正确调用了 scrollTo
方法,但应用程序中没有任何移动,它仍然显示为开始一直向左滚动。
因为这是 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;
我遇到了同样的问题,浪费了几个小时没有:
1: 在android中,ScrollView只有当它的大小<内容的大小时才能滚动
2:在react native中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");
})
}
这适用于 React Native 0.44.0。感谢@Eldelshell 的提示。它似乎也适用于任何超时值。至少在模拟器上。我发现涉及 InteractionManager.runAfterInteractions
的答案没有解决问题,但也许这是版本差异。
componentDidMount() {
setTimeout(() => {
this._scroll.scrollTo({y: 100})
}, 1)
}
我想避免使用延迟和计时器,所以经过一番挖掘后我发现使用 onLayout
工作非常顺利:
scrollToInitialPosition = () => {
this.scrollViewRef.scrollTo({ y: 100 });
}
...
<ScrollView
ref={(ref) => { this.scrollViewRef = ref; }}
onLayout={this.scrollToInitialPosition}
/>
谢谢@David Nathan,使用 InteractionManager
对我有用。
另请注意,与 setTimeout
不同,runAfterInteractions
不会延迟活动动画。
我认为应该有一个更现代的钩子版本:
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>)
}
我正在尝试在 React Native 中为 Android 使用 水平滚动视图,其中起始位置在滚动图像的中间而不是 (0, 0).
似乎在 componentDidMount
中正确调用了 scrollTo
方法,但应用程序中没有任何移动,它仍然显示为开始一直向左滚动。
因为这是 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;
我遇到了同样的问题,浪费了几个小时没有:
1: 在android中,ScrollView只有当它的大小<内容的大小时才能滚动
2:在react native中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");
})
}
这适用于 React Native 0.44.0。感谢@Eldelshell 的提示。它似乎也适用于任何超时值。至少在模拟器上。我发现涉及 InteractionManager.runAfterInteractions
的答案没有解决问题,但也许这是版本差异。
componentDidMount() {
setTimeout(() => {
this._scroll.scrollTo({y: 100})
}, 1)
}
我想避免使用延迟和计时器,所以经过一番挖掘后我发现使用 onLayout
工作非常顺利:
scrollToInitialPosition = () => {
this.scrollViewRef.scrollTo({ y: 100 });
}
...
<ScrollView
ref={(ref) => { this.scrollViewRef = ref; }}
onLayout={this.scrollToInitialPosition}
/>
谢谢@David Nathan,使用 InteractionManager
对我有用。
另请注意,与 setTimeout
不同,runAfterInteractions
不会延迟活动动画。
我认为应该有一个更现代的钩子版本:
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>)
}