React原生Android ScrollView scrollTo不工作

yqhsw0fo  于 2023-01-14  发布在  React
关注(0)|答案(6)|浏览(144)

我尝试在React Nativefor Android中使用水平ScrollView,其中起始位置位于滚动图像的中间,而不是(0,0)。
scrollTo方法似乎在componentDidMount中被正确调用,但应用程序中没有任何移动,它仍然显示为开始向左滚动。
由于这是Android,我没有访问contentOffset props的权限,或者我会直接设置它,根据文档。

'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;
cmssoen2

cmssoen21#

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

  • 1:在android中,ScrollView只有在其大小〈内容大小时才能滚动
  • 2:在react原生安卓系统中,如果您在componentDidMount中调用ScrollView.scrollTo(),它将不起作用,因为ScrollView在创建时具有布局动画,您可以在www.example.com中找到它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");
    })  
}
2hh7jdfx

2hh7jdfx2#

我想避免使用延迟和计时器,所以经过一番挖掘,我发现使用onLayout工作起来非常流畅:

scrollToInitialPosition = () => {
  this.scrollViewRef.scrollTo({ y: 100 });
}
...
<ScrollView
  ref={(ref) => { this.scrollViewRef = ref; }}
  onLayout={this.scrollToInitialPosition}
/>
xiozqbni

xiozqbni3#

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

componentDidMount() {
  setTimeout(() => {
    this._scroll.scrollTo({y: 100})
  }, 1)
}
cgyqldqp

cgyqldqp4#

我认为应该有一个更现代的,钩子的版本:

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>)

}
4nkexdtk

4nkexdtk5#

const [listIndex, setListIndex] = useState(inqId?list.findIndex(obj => 
obj.InqID == inqId):null);
const [ref, setRef] = useState(null)
scrollToPosition = () => {
  listRef.scrollTo({ y: 50*ref });
}

<ScrollView
  ref={(ref) => { setRef(ref) }}
  onLayout={scrollToPosition}
/>
332nm8kg

332nm8kg6#

谢谢@David Nathan,使用InteractionManager对我很有效。
还要注意,与setTimeout不同,runAfterInteractions将不延迟活动动画。
InteractionManager docs开始

相关问题