#127 "ScrollView in modal prevents modal from dismissing sometimes" - https://github.com/react-navigation/stack/issues/127
This issue has a good discussion and a comment:
brentvatne: it's not really possible for react-navigation to guess when you may or may not want to close the modal depending on other gestures you have inside of a scene, you need to define that behavior for yourself. you can access the gesture context like this: https://github.com/react-navigation/react-navigation-stack/blob/5f157cbc16f2dd15363304ab3c78663b0ed36de0/example/src/GestureInteraction.js#L55-L56 then you can use react-native-gesture-handler tools to make this behave how you like.
And:
ryan-gilb (Dec 29): Hey @skhavari! If you still need help with this, check out this snack: https://snack.expo.io/@rgilbert/scrollable-modal-with-dismissal
This seems to be a pretty clean version.
#315 "Document how to build a modal that dismisses by gesture only when ScrollView is at top" - react-navigation/react-navigation.github.io#315
This was based on issue #127. @ryan-gilb created a snack Dec 29 2018: https://snack.expo.io/@rgilbert/full-screen-modal-v3
This seems like the same version as above, but more raw. A temporary version? Anyhow, it exhibits the drag miss issue.
#333 "Document modal that dismisses by gesture only when ScrollView is at top" - react-navigation/react-navigation.github.io#333
Based on the additional issue, he created an example in Dec 29 2018: https://github.com/react-navigation/react-navigation.github.io/pull/333/files
Basically:
<StackGestureContext.Consumer>
{ref => (
<ScrollView
waitFor={this.state.scrolledTop ? ref : undefined}
onScroll={({ nativeEvent }) => {
const scrolledTop = nativeEvent.contentOffset.y <= 0;
this.setState({ scrolledTop });
}}
scrollEventThrottle={16}>
<Text>{content}</Text>
</ScrollView>
)}
</StackGestureContext.Consumer>
But it has an issue: it doesn't always work. Sometimes, pulling from the top uses the scroll view.
@brentvatne also had additional reservations:
Thanks for this! Love the writing style.
- The idea is right to prevent overscroll on the top when dismissing, however it doesn't disable the gesture when you're not at the top of the ScrollView. If you scroll down, release the gesture, then scroll up again it shouldn't dismiss the modal. We'd need to use gesturesEnabled and set it to false when the ScrollView isn't at the top (scroll offset <= 0, negative offset is overscroll bounce).
- We need to add some y offset failure criteria to the PanGestureHandler in https://github.com/react-navigation/react-navigation-stack/blob/master/src/views/StackView/StackViewLayout.js - right now there's a delay when you try to scroll.
- It may be easier to disable the gestures entirely and re-implement the gesture entirely for the modal, because I think we won't be able to implement it properly otherwise without adding y offset failure criteria. A good starting point would be this: https://github.com/react-navigation/react-navigation-stack/blob/master/example/src/TransparentStack.js
The file he's referring to is this:
Which got moved to this:
https://github.com/react-navigation/stack/blob/master/example/src/TransparentStack.tsx
But there's really not much there other than a different transition config.
defaultNavigationOptions: {
gestureEnabled: false,
cardTransparent: true,
cardStyleInterpolator: ({ current: { progress } }) => {
const opacity = Animated.interpolate(progress, {
inputRange: [0, 0.5, 0.9, 1],
outputRange: [0, 0.25, 0.7, 1],
});
return {
cardStyle: {
opacity,
},
};
},
},
Gesture works, but only sometimes.
Issues that report the same:
#166 ScrollViews conflict with the swipe back gesture on iOS - https://github.com/react-navigation/stack/issues/166
No solution.
Points to the (older) issue: https://github.com/react-navigation/stack/issues/137 that might be related to diagonal swiping?
For him, this seems to work:
With the limited time I had to look in to this I would guess that the pickiness has to do with the rather low maxDeltaY set in
src/views/StackView/StackViewLayout.tsx -> gestureActivationCriteria()
but I didn't have the time to try and change it. If someone has the time to try fiddling with this so we can get less annoyed when failing to swipe back in RN apps that would awesome!
GestureInteraction.js - https://github.com/react-navigation/stack/blob/1.0/example/src/GestureInteraction.js
An example from React-navigation-stack, using StackGestureContext
. Uses a if (!this.state.interactionComplete)
that was worth investigating:
InteractionManager.runAfterInteractions(() => {
this.setState({ interactionComplete: true });
});
But turns out this is useless to us. It only runs at the end of screen transitions (has nothing to do with gesture interactions, for example).
And #166 Also proposes a different implementation for waitFor
:
<NativeViewGestureHandler waitFor={ref}>
<ScrollView>...</ScrollView>
</NativeViewGestureHandler>
Or as in here:
<NativeViewGestureHandler waitFor={ref}>
<MapView style={{ flex: 1 }} />
</NativeViewGestureHandler>
But this has the same issues as a ReactNavigation.ScrollView with waitFor
.
Thanks for the comprehensive list of issues and tests related to nested in modals! 👍
Did you ever end up finding an elegant solution to this?