Javascript React Native 嵌套 ScrollView 锁定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29756217/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React Native nested ScrollView locking up
提问by nicholas
I'm trying to nest ScrollViews in React Native; a horizontal scroll with nested vertical scrolls.
我正在尝试将 ScrollViews 嵌套在 React Native 中;带有嵌套垂直滚动的水平滚动。
Here's an example:
下面是一个例子:
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);
The outer scroller works flawlessly, but the inner one sticks when you touch it while it's moving. What I mean is: if you scroll, lift your finger and touch it again while it's still moving with momentum, it stops and doesn't react at all to touch moves. To scroll more you have to lift your finger and touch again.
外部滚动条完美无缺,但内部滚动条在移动时触摸它时会粘住。我的意思是:如果你滚动,抬起你的手指并在它仍然以动量移动时再次触摸它,它会停止并且对触摸移动完全没有反应。要滚动更多,您必须抬起手指并再次触摸。
This is so reproducible it feels like something to do with the Gesture Responder.
这是非常可重复的,感觉就像是与手势响应器有关。
Has anyone seen this issue?
有没有人看到这个问题?
How would I even begin to debug this? Is there a way to see what's responding to touches, granting and releasing, and when?
我什至如何开始调试这个?有没有办法查看什么对触摸、授予和释放以及何时做出反应?
Thanks.
谢谢。
Update:
更新:
It looks like it is the responder system, by putting onResponderMovelisteners on the inner and outer scrollers:
看起来它是响应器系统,通过将onResponderMove侦听器放在内部和外部滚动条上:
<ScrollView
onResponderMove={()=>{console.log('outer responding');}}
...
<ScrollView
onResponderMove={()=>{console.log('inner responding');}}>
...
It's clear that the outer ScrollView is grabbing control. The question, I guess, is how do I stop the outer scroller from taking control when trying to scroll vertically? And why is this only happening when you try to scroll an already moving inner ScrollView?
很明显,外部 ScrollView 正在抢占控制权。我想,问题是如何在尝试垂直滚动时阻止外部滚动条控制?为什么只有当您尝试滚动已经移动的内部 ScrollView 时才会发生这种情况?
回答by Adam
If you are working with RN > 56.0, just add this prop to your scroll views:
如果您正在使用 RN > 56.0,只需将此道具添加到您的滚动视图中:
<ScrollView nestedScrollEnabled = {true}>
......
<ScrollView nestedScrollEnabled = {true}>
.....
</ScrollView>
</ScrollView>
That's the only one worked for me.
这是唯一对我有用的。
回答by rissk13
@IlyaDoroshin and @David Nathan's answer pointed me in the right direction but I had to wrap each item in the scrollview with a touchable, rather than one touchable for everything.
@IlyaDoroshin 和@David Nathan 的回答为我指明了正确的方向,但我必须用可触摸的方式将滚动视图中的每个项目包裹起来,而不是可触摸的所有内容。
<ScrollView>
...
<ScrollView horizontal>
{items.map(item => (
<TouchableWithoutFeedback>
{ /* your scrollable content goes here */ }
</TouchableWithoutFeedback>
))}
</ScrollView>
</ScrollView>
回答by Josh Baker
In your panresponder for the inner one, try setting this:
在您的内部响应器中,尝试设置:
onPanResponderTerminationRequest: () => false
回答by Shuangzuan He
Modify node_modules/react-native/Libraries/Components/ScrollResponder.js: Line 136 (See UPDATE):
修改node_modules/react-native/Libraries/Components/ScrollResponder.js:第 136 行(见更新):
scrollResponderHandleScrollShouldSetResponder: function(): boolean {
return this.state.isTouching;
},
UPDATE: I find if the scroll view is currently animating and wants to become the responder, then it will reject. Line 189 in ScrollResponder.js. So I modify Line 340 and it work for me:
更新:我发现如果滚动视图当前正在动画并且想要成为响应者,那么它会拒绝。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;
},
You can see here: https://github.com/facebook/react-native/issues/41
你可以在这里看到:https: //github.com/facebook/react-native/issues/41
回答by IlyaDoroshin
Wrapping scrollable content of nested ScrollView with fixed this one for me on android:
在 android 上为我修复了嵌套 ScrollView 的可滚动内容:
<ScrollView>
...
<ScrollView horizontal>
<TouchableWithoutFeedback>
{ /* your scrollable content goes here */ }
</TouchableWithoutFeedback>
</ScrollView>
</ScrollView>

