我正在尝试在 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 时才会发生这种情况?
如果您使用的是 RN > 56.0,只需将此道具添加到您的滚动视图中:
<ScrollView nestedScrollEnabled = {true}>
......
<ScrollView nestedScrollEnabled = {true}>
.....
</ScrollView>
</ScrollView>
这是唯一对我有用的。
@IlyaDoroshin 和 @David Nathan 的回答为我指明了正确的方向,但我必须用可触摸的方式将滚动视图中的每个项目包装起来,而不是对所有内容都使用可触摸的方式。
<ScrollView>
...
<ScrollView horizontal>
{items.map(item => (
<TouchableWithoutFeedback>
{ /* your scrollable content goes here */ }
</TouchableWithoutFeedback>
))}
</ScrollView>
</ScrollView>
在您的内部泛响应器中,尝试设置以下内容:
onPanResponderTerminationRequest: () => false
在 android 上为我修复了这个问题,从而包装嵌套 ScrollView 的可滚动内容:
<ScrollView>
...
<ScrollView horizontal>
<TouchableWithoutFeedback>
{ /* your scrollable content goes here */ }
</TouchableWithoutFeedback>
</ScrollView>
</ScrollView>
修改
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;
},
注意
在一些报告的案例中,从“react-native”导入的 ScrollView 现在可以正常工作。例如这个嵌套滚动问题,我什至尝试过
嵌套滚动启用
还是没成功
另一方面,从
导入ScrollView从'react-native-gesture-handler'导入{ScrollView};
即使没有nestedScollEnabled也能正常工作。
谢谢。