I'm working on a tab component in React-Native right now. So I have a View with a PanResponder as parent that handles horizontal gestures. However when I add a ScrollView as a child to that View, ScrollView sometimes intercepts horizontal gestures and becomes the responder. So when I'm swiping the right or left, it becomes the responserr in the middle of the gesture even though I'm not swiping vertically and PanResponder returns false onTerminationRequest [I'm aware that this does not guarantee a termination request rejection].
I looked at other questions and issues on GitHub page but it seems everyone is having the exact opposite of this problem where PanResponder intercepts ScrollView.
This is the pan responder:
this.panResponder = PanResponder.create({
// Ask to be the responder:
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {},
onPanResponderMove: (evt, gestureState) => {
if(this.state.checkScroll && this.state.checkScroll && Math.abs(gestureState.dx) > Math.abs(gestureState.dy)){
if(gestureState.dx > 0 && this.state.current != 0)
this.setState({current: this.state.current, next: this.state.current - 1, scroll: gestureState.dx, checkScroll: true, animating: false});
else if(gestureState.dx < 0 && this.state.current != this.props.children.length -1)
this.setState({current: this.state.current, next: this.state.current + 1, scroll: gestureState.dx, checkScroll: true, animating: false});
}
},
onPanResponderTerminationRequest: (evt, gestureState) => false,
onPanResponderRelease: (evt, gestureState) => {
if(!Math.abs(gestureState.dx) > Math.abs(gestureState.dy) || !this.state.checkScroll){
return;
}
if(gestureState.vx > 1 && gestureState.dx > 0)
this.switchTo(this.state.current - 1);
else if(gestureState.vx < -1 && gestureState.dx < 0)
this.switchTo(this.state.current + 1);
else if(Math.abs(gestureState.dx) > this.width / 2)
this.switchTo(this.state.current - Math.sign(gestureState.dx));
else
this.abortSwipe();
},
onPanResponderTerminate: (evt, gestureState) => {
if(!Math.abs(gestureState.dx) > Math.abs(gestureState.dy) || !this.state.checkScroll)
return;
if(gestureState.vx > 1 && gestureState.dx > 0)
this.switchTo(this.state.current - 1);
else if(gestureState.vx < -1 && gestureState.dx < 0)
this.switchTo(this.state.current + 1);
else if(Math.abs(gestureState.dx) > this.width / 2)
this.switchTo(this.state.current - Math.sign(gestureState.dx));
else
this.abortSwipe();
},
onShouldBlockNativeResponder: (evt, gestureState) => {
return true;
},
});
And this is the corresponding rendering part:
<View style={styles.tabBodyContainer} {...this.panResponder.panHandlers}>
{this.props.children.map((child, index)=>{
if(index == main.state.current){
return <Animated.View key={index} style={[styles.tabBodyView, {left: main.state.animating ? firstSeed : main.state.scroll}]}>{child}</Animated.View>;
}
else if(index == main.state.next){
if(index < main.state.current)
return <Animated.View key={index} style={[styles.tabBodyView, {right: main.state.animating ? secondSeed : (main.width - main.state.scroll)}]}>{child}</Animated.View>;
else
return <Animated.View key={index} style={[styles.tabBodyView, {left: main.state.animating ? secondSeed : (main.state.scroll + main.width)}]}>{child}</Animated.View>;
}
else
return;
})}
</View>
So anyone know have can I solve this problem?