React Native 嵌套 ScrollView 锁定

问题描述 投票:0回答:6

我正在尝试在 React Native 中嵌套 ScrollViews;带有嵌套垂直滚动条的水平滚动条。

这是一个例子:

var Test = React.createClass({
    render: function() {
        return (
            <ScrollView
                style={{width:320, height:568}}
                horizontal={true}
                pagingEnabled={true}>

                {times(3, (i) => {
                    return (
                        <View style={{width:320, height:568}}>

                            <ScrollView>
                                {times(20, (j) => {
                                    return (
                                        <View style={{width:320, height:100, backgroundColor:randomColor()}}/>
                                    );
                                })}
                            </ScrollView>

                        </View>
                    );
                })}

            </ScrollView>
        );
    },
});

AppRegistry.registerComponent('MyApp', () => Test);

外滚动条工作完美,但是当你在它移动时触摸它时,内滚动条会粘住。我的意思是:如果你滚动、抬起手指并在它仍在移动时再次触摸它,它会停止并且对触摸移动完全没有反应。要滚动更多内容,您必须抬起手指并再次触摸。

这是如此可重复,感觉就像与手势响应器有关。

有人见过这个问题吗?

我该如何开始调试这个?有没有办法查看什么对触摸、授予和释放以及何时做出响应?

谢谢。

更新:

它看起来像是响应者系统,通过将

onResponderMove
监听器放在内部和外部滚动条上:

<ScrollView 
    onResponderMove={()=>{console.log('outer responding');}}
    ...

    <ScrollView
        onResponderMove={()=>{console.log('inner responding');}}>
        ...

很明显,外层ScrollView正在抢夺控制权。我想问题是当尝试垂直滚动时如何阻止外部滚动器获得控制权?为什么只有当您尝试滚动已经移动的内部 ScrollView 时才会发生这种情况?

javascript react-native
6个回答
81
投票

如果您使用的是 RN > 56.0,只需将此道具添加到您的滚动视图中:

<ScrollView nestedScrollEnabled = {true}>
 ......
  <ScrollView nestedScrollEnabled = {true}>
    .....
  </ScrollView>
</ScrollView>

这是唯一对我有用的。


10
投票

@IlyaDoroshin 和 @David Nathan 的回答为我指明了正确的方向,但我必须用可触摸的方式将滚动视图中的每个项目包装起来,而不是对所有内容都使用可触摸的方式。

<ScrollView>
  ...
  <ScrollView horizontal>
    {items.map(item => (
        <TouchableWithoutFeedback>
          { /* your scrollable content goes here */ }
        </TouchableWithoutFeedback>
    ))}
  </ScrollView>
</ScrollView>

9
投票

在您的内部泛响应器中,尝试设置以下内容:

onPanResponderTerminationRequest: () => false

8
投票

在 android 上为我修复了这个问题,从而包装嵌套 ScrollView 的可滚动内容:

<ScrollView>
  ...
  <ScrollView horizontal>
    <TouchableWithoutFeedback>
      { /* your scrollable content goes here */ }
    </TouchableWithoutFeedback>
  </ScrollView>
</ScrollView>

5
投票

修改

node_modules/react-native/Libraries/Components/ScrollResponder.js
:第136行(参见更新):

scrollResponderHandleScrollShouldSetResponder: function(): boolean {
    return this.state.isTouching;
},

更新:我发现如果滚动视图当前正在动画并且想要成为响应者,那么它会拒绝。 ScrollResponder.js 中的第 189 行。所以我修改了第 340 行,它对我有用:

scrollResponderIsAnimating: function(): boolean {
  // var now = Date.now();
  // var timeSinceLastMomentumScrollEnd = now - this.state.lastMomentumScrollEndTime;
  // var isAnimating = timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS ||
  //   this.state.lastMomentumScrollEndTime < this.state.lastMomentumScrollBeginTime;
  // return isAnimating;
    return false;
},

您可以在这里看到:https://github.com/facebook/react-native/issues/41


0
投票

注意

在一些报告的案例中,从“react-native”导入的 ScrollView 现在可以正常工作。例如这个嵌套滚动问题,我什至尝试过

嵌套滚动启用

还是没成功

另一方面,从

导入ScrollView

从'react-native-gesture-handler'导入{ScrollView};

即使没有nestedScollEnabled也能正常工作。

谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.