React原生Android ScrollView scrollTo无法正常工作

Rob*_*b M 23 scrollview react-native react-native-android

我试图在React Native for Android中使用水平ScrollView,其中起始位置位于滚动图像的中间而不是(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;
Run Code Online (Sandbox Code Playgroud)

小智 43

我有同样的问题,浪费了几个小时没有它:

  • 1:在android中,ScrollView只能在其大小<内容的大小时滚动

  • 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());
}
Run Code Online (Sandbox Code Playgroud)

所以,你必须在动画后延迟它

componentDidMount() {
    InteractionManager.runAfterInteractions(() => {
      this.myScroll.scrollTo(100);
        console.log("called DidMount");
    })  
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案有效,但我不得不在这个函数中添加一个延迟:`_.delay(()=> this._scroll.scrollTo({x:1000,animated:false}),100);` (2认同)

Phi*_*ilT 16

这适用于React Native 0.44.0.感谢@Eldelshell的提示.它似乎也适用于任何超时值.至少在模拟器上.我发现答案涉及InteractionManager.runAfterInteractions没有解决问题,但也许这是版本的差异.

componentDidMount() {
  setTimeout(() => {
    this._scroll.scrollTo({y: 100})
  }, 1)
}
Run Code Online (Sandbox Code Playgroud)

  • 此答案假设 ScrollView 的初始动画在 1 毫秒内完成。大多数情况下可能会发生这种情况,但不能保证。这就是为什么 `InteractionManager.runAfterInteractions()` 是首选的解决方案,而 `setTimeout()` 有点草率。 (2认同)
  • @NathanK你没有读菲尔的回答。他明确表示使用“InteractionManager”并没有解决他的问题。它也没有解决我的问题。我能找到解决此问题的唯一解决方案是使用较低值的“setTimeout”。 (2认同)
  • 对我来说也是如此,它不与“InteractionManager.runAfterInteractions”一起使用,而是与“setTimeout”一起使用 (2认同)

小智 7

我想避免使用延迟和计时器,因此,经过一番挖掘,我发现使用起来onLayout非常顺畅:

scrollToInitialPosition = () => {
  this.scrollViewRef.scrollTo({ y: 100 });
}
...
<ScrollView
  ref={(ref) => { this.scrollViewRef = ref; }}
  onLayout={this.scrollToInitialPosition}
/>
Run Code Online (Sandbox Code Playgroud)