Doesn't work in a modal
martinezguillaume opened this issue Β· 101 comments
Hi !
I have a little issue on Android, onGestureEvent
is not trigger when GestureHandler components is on a modal on Android. When I change the modal to a View, it works perfectly π
No problem on iOS
+1
any workaround?
I donβt use Modal for now, I just re-create it with a View in absolute position
using modal screen for now, after googling and chats Modal from RN considered too much buggy thing
+1
Hi, @martinezguillaume, @mordaha, @csto
I did take a look on this issue and I suppose it's not a matter of our library, but RN Core.
+1 gesture does not work on modal
I also ran into this bug today.
Same problem. Gesture does not work on modal on Android.
Expo for example
Same for me. Tested react-native's PanResponder handlers on modal - works fine.
I have a thoughts about this: when we are linking this library to android project, we are doing next step
@Override
protected ReactRootView createRootView() {
return new RNGestureHandlerEnabledRootView(MainActivity.this);
}
And we know that modal is separate package. May be theres sense to do something same with it?
I was using a standard React Native Modal
and was experiencing this issue.
I worked around the problem by creating a new screen and displaying it as a modal. I'm using react-native-navigation, so:
Navigation.showModal({
component: {
name: navRoutes.ImageModal,
passProps: { image },
},
})
Gestures are working as expected on both iOS and Android, and I still get transparent background that I wanted from my original modal.
I have dug into it for a while.
- It's a problem of RNGH. Sorry π
- It happens bc modals are not rendered below an RN root view.
- It's fixable by replacing modals' mechanism in a similar way as we do with an RNRootView by wrapping it with some extra logic. See https://github.com/kmagiera/react-native-gesture-handler/blob/master/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootViewManager.java
- I have no time to do it now, it's time-consuming work and probably requires copying some code in an RNGH core on Android native side.
If someone wants and has time to do it, I'll happily review it and merge immediately if it would be workable and not too hacky.
@martinezguillaume @mordaha @csto @mars-lan @ParhamZare @ewendel @via-profit @Dmitrylolo @Lavielle
Also, I've made a try two months ago.
Maybe it could be an inspiration for someone π€·ββοΈ
Hey @osdnk I need this feature for my app, so I was thinking I could give it a try, but I don't have a lot of experience with RNGestureHandler, or with Android. Could you give me some more insight on what I would need to do to make it work ?
Also I was looking at your previous try, and I would like to know what's missing for it to be finished, and if it could be used as a starting point.
same error.
+1. i use reanimated-bottom-sheet with modal
Any updates? Or perhaps, any other modal component that does not suffer from this issue? RN's modal honestly works like quite bad and is full of bugs (such as getting stuck if combined with an alert)
@cristianoccazinsp It only uses RN's modal to cover the screen, which can be disabled by setting coverScreen
to false
@cristianoccazinsp It only uses RN's modal to cover the screen, which can be disabled by setting
coverScreen
tofalse
But is there a way how to show fullscreen modal with this prop which is not rendered in root component of the app?
@jvaclavik I used it in conjunction with https://github.com/callstack/react-native-paper, which has a component called Portal designed specifically for this purpose.
This may not resolve all use cases but you can enable gestures in react native modal when setting the prop propagateSwipe
to true.
This issue seems to be related to software-mansion/react-native-screens#61
Don't use react native screens in android. Tested and working fine with 'reanimated-bottom-sheet'
if (Platform.OS === 'ios') {
useScreens();
}
This React Navigation Modal config for transparent bg is
ScreenOne: {
screen: ScreenOne,
navigationOptions: {
gesturesEnabled: false
},
}
{
mode: 'modal',
transparentCard: true,
headerMode: 'none',
cardStyle: {
backgroundColor: 'transparent',
opacity: 1
},
transitionConfig: () => ({
containerStyle: {
backgroundColor: 'transparent',
}
})
}
@osdnk fixed it?
This one is was so much pain.
I've spend some time before resolving to google it, pull my hairs out trying to figure out why on earth same component works on iOS and on android but only in some places inside application
we have the same issue - it doesn't work on modal.
i wonder if anyone is working on this or know of any status update ?
do we need to drop this library and switch to RN pan handlers ?
any suggestion ?
https://github.com/react-native-community/react-native-modal doesn't work too
Same here. RectButton doesn't work inside https://github.com/react-native-community/react-native-modal
@deflorilemarului @kesha-antonov @fauker
Will spare you some time, neither Modal
, nor Modal
-based packages (if they don't require you to link native dependencies - they are based on react-native
's Modal
) will help you (I've tried all of them, basically).
All of gesture-
related components (bottomsheet-behaviour for us) will not register any touches/swipes etc when rendered inside <Modal>...</Modal>
on android;
There is 3 solutions I can think of:
- Use any other library if you are using modals. You may require rewrite some swipe-based components to
PanResponder
; this on is pain, but pretty straightforward; - Use modals that are
portals
. They are not actually portals nor modals- portals are not supported by react-native because there is single application host - but they are working by placing Host Component somewhere up your application and renders Modal content in absolute view above app stack; this one is working solution, but you will loose anyuseContext()
calls due to children being rendered above context providers; does not work for us, sincenavigation
context is lost; - Use modals provided by navigation library (
react-navigation
); this one works, but API is... not good - for one you could not make a single screen a modal, only a stack can be in modal mode; this one is solution I stick with.
Well, there is final solution - patch native android implementation (not possible if you are using expo) or wait for patch in a library and then wait until it merged into expo.
p.s.
Don't get me wrong, this library is amazing, and I cannot stress enough how much I appreciate work being poured into this and how much better the experience for end user, but bugs like this one make me want to pull my hairs out.
Few libraries requires us to deal with native context, if so:
For android, we will need a special care as stated in RNGH document:
Update your MainActivity.java
file
Hope it helps
Few libraries requires us to deal with native context, if so:
For android, we will need a special care as stated in RNGH document:
Update your
MainActivity.java
file
Hope it helps
Yes, this worked perfectly for me. I almost got frustrated looking for solutions on making my android app swippable.
still not working
if change modal to view everything work just fine...
Hi @romanonthego ,
Well, there is final solution - patch native android implementation (not possible if you are using expo) or wait for patch in a library and then wait until it merged into expo.
Can you please tell me what to patch in side my native android code?
@osdnk That's exciting. Will it work with a DialogFragment
as well?
After trying #937 I found out it didn't work for me...
Maybe it's because I'm using wix's react-native-navigation? As far as I know each and every screen is registered with the gestureHandlerRootHOC (the library works perfectly with normal, non modal views).
This is a fragment of the screen in which I tried the RectButton in a Modal (basically as it is in the doc update)
renderSearchScreen = () => {
const { showSearchHistory } = this.state;
const ExampleWithHoc = gestureHandlerRootHOC(() => {
return (
<View style={genericStyles.container}>
<SearchScreen
searchBar={{
...this.searchBar,
searchQuery: this.props.searchQuery,
}}
onBackPress={() => {
this.setState({ showSearchHistory: false });
}}
/>
</View>
);
});
if (showSearchHistory) {
return (
<RNModal
animationType="fade"
transparent
visible={this.state.showSearchHistory}
onRequestClose={() => {}}>
<ExampleWithHoc />
</RNModal>
);
}
return null;
};
The modal loads when it's supposed to, but the RectButton does not fire the onPress event. I tried making a minimum reproducible demo with a brand new app but then I ran into #848 #676 #835 (possible duplicates of one another).
whop #937
That's amazing! It still doesn't work with react-native-modal
for me, though!
// edit: Actually, default modal doesn't work either, but it should, starting from 1.6.0 if I am not mistaken? Will try to find out what's going wrong
I've played around a bit and was able to find the issue. However, I am not sure what's causing it and how to fix it.
The problem in my case is, that I react-native-gesture-handler
will not work inside a @react-navigation/stack
, if placed inside a modal (so basically Stack.Navigator
> SomeScreenComponent
> Modal
> gestureHandlerRootHOC(PanGestureHandler)
fails).
If I cut the Stack Navigator out or use the Tab Navigator instead, it works like a charm, so I am pretty sure it's the Stack Navigators' fault.
Relevant package versions:
react-native@0.61.5
@react-navigation/native@5.0.9
@react-navigation/stack@5.1.1
I'll try to setup a demo repo ASAP, let me know if I can provide any more helpful info.
Here is a demo app to (almost blank from npx react-native init
), that will show the issue. You can toggle the stack navigator inside the app and see how the PanGestureHandler
becomes functional and unfunctional.
I have a similar issue. It seems that the Stack.Navigator doesn't work well on Android. It doesn't matter if I use a mode="modal" or "card".
So i was playing around and had the following code
import { SafeAreaView, Button } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack'
import { enableScreens } from 'react-native-screens';
enableScreens(); // <-- this fucked it up
const Screen1 = ({ navigation }) => {
return (
<SafeAreaView style={{ flex: 1 }}>
<Button title="Open Modal" onPress={() => navigation.push('Modal')} />
</SafeAreaView>
)
}
const Screen2 = ({ navigation }) => {
return (
<SafeAreaView style={{ flex: 1 }}>
<Button title="Close Modal" onPress={() => navigation.goBack()} />
</SafeAreaView>
)
}
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator headerMode="none">
<Stack.Screen name="Main" component={Screen1} />
<Stack.Screen name="Modal" component={Screen2} />
</Stack.Navigator>
</NavigationContainer>
)
}
Then I removed this line;
enableScreens();
And then it worked correctly on Android.
A little trick to solve it inside a modal:
import { TouchableWithoutFeedback } from 'react-native';
import { RectButton } from 'react-native-gesture-handler';
<TouchableWithoutFeedback onPress={...}
<RectButton>
...
</RectButton>
</TouchableWithoutFeedback>
I am having similar issue. Any work around ?
I was trying to use https://github.com/osdnk/react-native-reanimated-bottom-sheet inside a modal, and it's not possible, I finally solved with react-navigation screen animation:
A little trick to solve it inside a modal:
import { TouchableWithoutFeedback } from 'react-native'; import { RectButton } from 'react-native-gesture-handler';<TouchableWithoutFeedback onPress={...} <RectButton> ... </RectButton> </TouchableWithoutFeedback>
Hey @gideaoms . I wonder how did your comment went unnoticed here. It definitely does the trick. Thanks man!
Here is a demo app to (almost blank from
npx react-native init
), that will show the issue. You can toggle the stack navigator inside the app and see how thePanGestureHandler
becomes functional and unfunctional.
then, what is the solution?
I'm still having the same problem....
Any solution ou nothing yet ?
This is still a problem on 1.6.0
Tried every suggestions mentioned above but still no luck yet. Please help its really frustrating.
My react native version in 0.62.2 tried with both /react-native-gesture-handler 1.5.6 & 1.6.0.
still an issue on ^1.7.0
Is still not working π
We use wix-navigation. Maybe something related?
Well, I found a possible workaround, it does exactly what we want and work for both iOS and Android.
@steniowagner is that like a custom modal ? I wouldn't recommend it
just go with react-navigations or native-stack modal, it does work with it fine.
hmm, didn't test with react-navigations (sounded like too much for my case), but maybe it's the best way at the moment.
Thank you @a-eid !
According to the docs
https://docs.swmansion.com/react-native-gesture-handler/docs/#usage-with-modals-on-android
but still didn't work for me.
@gideaoms that tricks may works for button but my use case is to use PinchGestureHandler
inside the modal.
A little trick to solve it inside a modal:
import { TouchableWithoutFeedback } from 'react-native'; import { RectButton } from 'react-native-gesture-handler';<TouchableWithoutFeedback onPress={...} <RectButton> ... </RectButton> </TouchableWithoutFeedback>
This issue is more than 2 years old, are there any plans to fix this?
I've created custom Slider components for my app and can't use them at all on Android, since a lot of views in my app are Modals
I've wrapped every screen and Modal component in a gestureHandlerRootHoC
(using wix/react-native-navigation)
I've tried wrapping both the screen and the component with gestureHandlerRootHoc
without success. I didn't try the RectButton
approach because I need a PanGestureHandler
in order to implement swipe-down-to-dismiss behaviour on the modal. It is frustrating because it works perfectly on iOS and, since I'm using react-native-modal
, which actually comes with swipe-to-dismiss out-of-the-box, I've even tried using that approach instead and it works as long as you don't have scrollable content inside the modal because then it's buggy both on iOS and Android, so I'm kind of stuck...
To sum up:
- β RNGH does not work in
react-native
's<Modal>
component (even though the Component is wrapped in agestureHandlerRootHOC
) - β
RNGH does work in a screen from
wix/react-native-navigation
's which is shown usingNavigation.showModal
(even though the Screen is wrapped in agestureHandlerRootHOC
) - β
RNGH apparently does work if shown using
react-navigation
's push function withmodal: true
, but only when not using the native stack (enableScreens()
/createNativeStackNavigator()
).
I can provide more details if required.
react-native-modal-animated works with react-native-gesture-handler, because react-native-modal-animated creating a Modal just using a View.
@flyskywhy if react-native-modal-animated doesn't use a separate activity like react-native-modal then how it's render on top of everything? If it's using an absolute position then it could make a problem in some cases.
@waheedakhtar694 , it's using absolute. At least in my case, no problem π
@jvaclavik I used it in conjunction with https://github.com/callstack/react-native-paper, which has a component called Portal designed specifically for this purpose.
Solved using Portal from react-native-paper as @jvaclavik said.
I wrapped my App with PaperProvider, then changed Modals to Views and wrapped them with gestureHandlerRootHOC and Portal.
Now bottom-sheet works on Android π
EDIT: for some reason pan gestures are working but onPress events are not working (but ripple is shown)...
EDIT 2: that was a problem with the library I used, I fixed it changing touchable imports from "react-native" to "react-native-gesture-handler"
Here's some code you can try
/*
App.js:
- import { Provider as PaperProvider } from "react-native-paper";
- wrap your App with PaperProvider
*/
// ModalFixed.js
import { Portal } from 'react-native-paper';
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
const ModalFixed = (props) => {
<View style={styles.modal}>
<View style={styles.shadow} />
{/* MODAL CONTENT HERE, you can put props.children to reuse this component */}
</View>
}
const styles = StyleSheet.create({
modal: {
width: "100%",
height: "100%"
},
shadow: {
position: "absolute",
width: "100%",
height: "100%",
backgroundColor: "rgba(0,0,0,0.3)",
}
})
const _ModalFixed = gestureHandlerRootHOC(SheetPopup)
export default (props) => {
return (
<Portal>
<_ModalFixed {...props} />
</Portal>
)
}
Its working for me:
<TouchableWithoutFeedback onPress={() => { console.log("press"); }} > <Text> <RectButton> ... </RectButton> </Text> </TouchableWithoutFeedback>
Any update on this? We have two projects where iOS is working as expected but Android modals are proving a headache. We'd rather not have to remove modals from the projects...that is a big design overhaul. :/
@DavidAPears have you tried wrapping you modals in gestureHandlerRootHOC
?
something like this ?
const ModalInner = gestureHandlerRootHOC(function GestureExample() {
return (
<View>
{ RNGH components . }
</View>
);
});
export default function ModalForX() {
return (
<Modal animationType="slide" transparent={false}>
<ModalInner />
</Modal>
);
}
Combination of Portal
from react-native-portalize
and gestureHandlerRootHOC
works for me. Something like that:
<Portal>
<Modal>
<GestureHandlerRootHOCWrappedComponent />
</Modal>
</Portal>
setting coverSreen={false} on modal works. But need my modal cover the screen
import {Platform, Modal} from 'react-native';
import {gestureHandlerRootHOC} from 'react-native-gesture-handler';
import {AnimatedBottomSheet} from '../AnimatedBottomSheet';
const AnimatedBottomSheetWrapper = Platform.OS === 'android' ? gestureHandlerRootHOC(AnimatedBottomSheet) : AnimatedBottomSheet;
Not sure if this is going to help someone, i also had issues using this library with react-native-modal, but beside wrapping children of modal gestureHandlerRootHOC (this is working fine for buttons, but i had issues having text input in modal + avoidKeyboard = true and on every press of key, keyboard was closing ) So only thing i did, is made modal children wrapper, something like this:
import Modal from 'react-native-modal';
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
const GestureHandlerWrapper = gestureHandlerRootHOC(
({ children }) => <View>{children}</View>,
{ flex: 0 }
);
export const CustomModal: React.FC<Props> = ({
children,
...rest
}) => {
return (
<Modal
{...rest}
>
<GestureHandlerWrapper>
{children}
</GestureHandlerWrapper>
</Modal>
);
};
Yes, I saw that it is issue of Android after commenting, my bad π
setting coverSreen={false} on modal works. But need my modal cover the screen
It works for me, thanks.
If you want to cover the screen , you can make a customed modal componnet and put it at the top level of component tree, then set style to cover screen, you can set children component (modal content) by Ref.
I got this working using the suggestion for Library authors
<Modal>
<GestureHandlerRootView style={{width:'100%', height:'100%'}}>
<myGestureEnabledComponent/>
</GestureHandlerRootView>
</Modal>
Only tested on my Pixel 5 so far, but things are looking good so far π
I got this working using the suggestion for Library authors
<Modal> <GestureHandlerRootView style={{width:'100%', height:'100%'}}> <myGestureEnabledComponent/> </GestureHandlerRootView> </Modal>
Only tested on my Pixel 5 so far, but things are looking good so far
Works for nexus5x emulator.
Wrapping your component in worked for me seamlessly!
After a whole day of debugging
- You need to wrap you RNGH components in gestureHandlerRootHOC
- Upgrade from v1.8.0 to v1.10.3
- Wrap the modal in react-native-paper's
<Portal>
- Make sure the react native paper provider is the first component to render
When I did this it did not work:
However this worked:
if i skip any one of these steps it does not work
No at first I thought I use portal from paper and everything gets magically solved.
But use a textview in your modal now :)
It starts sucking.
To sum up:
- β RNGH does not work in
react-native
's<Modal>
component (even though the Component is wrapped in agestureHandlerRootHOC
)- β RNGH does work in a screen from
wix/react-native-navigation
's which is shown usingNavigation.showModal
(even though the Screen is wrapped in agestureHandlerRootHOC
)- β RNGH apparently does work if shown using
react-navigation
's push function withmodal: true
, but only when not using the native stack (enableScreens()
/createNativeStackNavigator()
).I can provide more details if required.
if you had examples it would be great.
setting coverSreen={false} on modal works. But need my modal cover the screen
It works for me, thanks.
If you want to cover the screen , you can make a customed modal componnet and put it at the top level of component tree, then set style to cover screen, you can set children component (modal content) by Ref.
not worked when using stack of react-navigation
I got this working using the suggestion for Library authors
<Modal> <GestureHandlerRootView style={{width:'100%', height:'100%'}}> <myGestureEnabledComponent/> </GestureHandlerRootView> </Modal>
Only tested on my Pixel 5 so far, but things are looking good so far
Works for nexus5x emulator.
not worked when using stack of react-navigation
After a whole day of debugging
- You need to wrap you RNGH components in gestureHandlerRootHOC
- Upgrade from v1.8.0 to v1.10.3
- Wrap the modal in react-native-paper's
<Portal>
- Make sure the react native paper provider is the first component to render
When I did this it did not work:
However this worked:
if i skip any one of these steps it does not work
not worked when using stack of react-navigation
Months passed, I can't wait any more, to use react-native-gesture-handler in a modal when using stack of react-navigation, now I publish an @flyskywhy/react-native-modal-animated
to npmjs.org, which is forked from rafalkaczynsky/react-native-modal-animated, and replaced componentWillReceiveProps
by React Hooks to support latest React.
RNGH works in a react native Modal if you wrap ONLY the content of the Modal in the GestureHandlerRootView
component (see RNGH docs, this comment and this pull request).
But if you wrap the whole app (or a screen that contains the Modal) in GestureHandlerRootView
too, RNGH buttons stops working inside the Modal (see why below).
Examples
Example of GestureHandlerRootView
used only inside a Modal:
const GHRVInsideModal: React.FC = () => {
const [visible, setVisible] = useState(false);
return (
<>
<TouchableOpacity onPress={() => setVisible(true)}>
<Text>Open (it's RN button) - it works</Text>
</TouchableOpacity>
<Modal
animationType="slide"
transparent
visible={visible}
>
<View style={styles.modal}>
<RectButton onPress={() => setVisible(false)}>
<Text>Close (it's RNGH button outside GestureHandlerRootView) - it does not work</Text>
</RectButton>
<GestureHandlerRootView>
<RectButton onPress={() => setVisible(false)}>
<Text>Close (it's RNGH button inside GestureHandlerRootView) - it works</Text>
</RectButton>
</GestureHandlerRootView>
</View>
</Modal>
</>
);
};
Example of nested GestureHandlerRootView
:
const NestedGHRV: React.FC = () => {
const [visible, setVisible] = useState(false);
return (
<GestureHandlerRootView>
<RectButton onPress={() => setVisible(true)}>
<Text>Open (it's RNGH button) - it works</Text>
</RectButton>
<Modal
animationType="slide"
transparent
visible={visible}
>
<View style={styles.modal}>
<GestureHandlerRootView>
<RectButton onPress={() => setVisible(false)}>
<Text>Close (it's RNGH button inside GestureHandlerRootView) - it does not work</Text>
</RectButton>
<TouchableOpacity onPress={() => setVisible(false)}>
<Text>Close (it's RN button) - it works</Text>
</TouchableOpacity>
</GestureHandlerRootView>
</View>
</Modal>
</GestureHandlerRootView>
);
};
Video with two examples:
Screen.Recording.2021-06-29.at.15.06.01.mov
See this repo with two examples.
React navigation
If you create a Modal inside react-navigation's stack and wrap the content of the Modal in GestureHandlerRootView
as the documentation says, it reproduces the second example and RNGH buttons in a Modal will not work.
This is happening because react-navigation wraps the stack content in GestureHandlerRootView
and your GH root view in a Modal renders as a simple View
.
How to fix
Why does the button in the Modal work in the first case, but not in the second?
If we look at the 17th line of the GestureHandlerRootView.android.tsx file we see, that nested gesture handler root views renders as View
. If you try to delete 17-22 lines from the GestureHandlerRootView.android.tsx
file the second example will start working.
Video reproduced what will be if you delete 17-22 lines from the GestureHandlerRootView.android.tsx
file (uploaded to YouTube, because GitHub does not allow uploading large files):
As a result, if the nested GestureHandlerRootView
is NOT rendered as a simple View
, RNGH buttons in a Modal in Android will work. I created a pull request #1493 that fixes it.
After a whole day of debugging
- You need to wrap you RNGH components in gestureHandlerRootHOC
- Upgrade from v1.8.0 to v1.10.3
- Wrap the modal in react-native-paper's
<Portal>
- Make sure the react native paper provider is the first component to render
When I did this it did not work:
However this worked:
if i skip any one of these steps it does not worknot worked when using stack of react-navigation
I got this to work! Using react-navigation and react-native-paper. Amazing, thank you @mfy5013
The use of react-native-portalize
fixed this perfectly for me while using React Navigation - here is a fully working Expo Snack for anyone that wants a minimal example of how to get this working in their own project:
https://snack.expo.dev/@thomascoldwell/react-navigation---rngh-root-view-bug-android---portal-fix
@jakub-gonet When are you planning the next release with #1603 changes?
We're planning on releasing the next version in a month or so. This is a transition from 1.x to 2.x so it may take a bit longer than usual.
I'm trying to call the RectButton inside a modal of createStackNavigator(@react-navigation/stack), on android the RectButton doesn't trigger onPress, IOS works perfectly
react-native-gesture-handler: 2.1.1
@react-navigation/native: ^6.0.6
@react-navigation/stack: ^6.0.11
Any solution?
The use of
react-native-portalize
fixed this perfectly for me while using React Navigation - here is a fully working Expo Snack for anyone that wants a minimal example of how to get this working in their own project:
https://snack.expo.dev/@thomascoldwell/react-navigation---rngh-root-view-bug-android---portal-fix
Thanks a lot finally this solution worked for me. :)
need more assistance.! can you please help me with this?
For me, I just installed the newest version 2.4.0. And then I use GestureHandlerRootView to wrapper the PanGestureHandler. It works. Remember that don't wrapper the view or others components. Wrapper thePanGestureHandler like below:
const $panelView = (
<GestureHandlerRootView>
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View style={[styles.panelView, panelStyle]}>
{$contentView}
</Animated.View>
</PanGestureHandler>
</GestureHandlerRootView>
)
For me, I just installed the newest version 2.4.0. And then I use GestureHandlerRootView to wrapper the PanGestureHandler. It works. Remember that don't wrapper the view or others components. Wrapper thePanGestureHandler like below:
const $panelView = ( <GestureHandlerRootView> <PanGestureHandler onGestureEvent={onGestureEvent}> <Animated.View style={[styles.panelView, panelStyle]}> {$contentView} </Animated.View> </PanGestureHandler> </GestureHandlerRootView> )
This fix does make the component scrollable but it's still super glitchy on android compared to when using the same component outside of a modal.
This happened to me too and belive it or not I solved it by setting backgroundColor
of the GesturHandler
content (the inner View
) to transparent
(or any value)
I'm guessing because react-native optimizes views only used for positioning their children and removes them or something and having a backgroundColor
forces it to keep the view (please correct me if I'm wrong).
Still not working on Android π
const ExampleWithHoc = gestureHandlerRootHOC(() => (
<View>
<DraggableBox />
</View>
);
);
export default function Example() {
return (
<Modal>
<ExampleWithHoc />
</Modal>
);
}
RNGH works in a react native Modal if you wrap ONLY the content of the Modal in the
GestureHandlerRootView
component (see RNGH docs, this comment and this pull request).But if you wrap the whole app (or a screen that contains the Modal) in
GestureHandlerRootView
too, RNGH buttons stops working inside the Modal (see why below).Examples
Example of
GestureHandlerRootView
used only inside a Modal:const GHRVInsideModal: React.FC = () => { const [visible, setVisible] = useState(false); return ( <> <TouchableOpacity onPress={() => setVisible(true)}> <Text>Open (it's RN button) - it works</Text> </TouchableOpacity> <Modal animationType="slide" transparent visible={visible} > <View style={styles.modal}> <RectButton onPress={() => setVisible(false)}> <Text>Close (it's RNGH button outside GestureHandlerRootView) - it does not work</Text> </RectButton> <GestureHandlerRootView> <RectButton onPress={() => setVisible(false)}> <Text>Close (it's RNGH button inside GestureHandlerRootView) - it works</Text> </RectButton> </GestureHandlerRootView> </View> </Modal> </> ); };Example of nested
GestureHandlerRootView
:const NestedGHRV: React.FC = () => { const [visible, setVisible] = useState(false); return ( <GestureHandlerRootView> <RectButton onPress={() => setVisible(true)}> <Text>Open (it's RNGH button) - it works</Text> </RectButton> <Modal animationType="slide" transparent visible={visible} > <View style={styles.modal}> <GestureHandlerRootView> <RectButton onPress={() => setVisible(false)}> <Text>Close (it's RNGH button inside GestureHandlerRootView) - it does not work</Text> </RectButton> <TouchableOpacity onPress={() => setVisible(false)}> <Text>Close (it's RN button) - it works</Text> </TouchableOpacity> </GestureHandlerRootView> </View> </Modal> </GestureHandlerRootView> ); };Video with two examples:
Screen.Recording.2021-06-29.at.15.06.01.mov
See this repo with two examples.React navigation
If you create a Modal inside react-navigation's stack and wrap the content of the Modal in
GestureHandlerRootView
as the documentation says, it reproduces the second example and RNGH buttons in a Modal will not work.This is happening because react-navigation wraps the stack content in
GestureHandlerRootView
and your GH root view in a Modal renders as a simpleView
.How to fix
Why does the button in the Modal work in the first case, but not in the second?
If we look at the 17th line of the GestureHandlerRootView.android.tsx file we see, that nested gesture handler root views renders as
View
. If you try to delete 17-22 lines from theGestureHandlerRootView.android.tsx
file the second example will start working.Video reproduced what will be if you delete 17-22 lines from the
GestureHandlerRootView.android.tsx
file (uploaded to YouTube, because GitHub does not allow uploading large files):As a result, if the nested
GestureHandlerRootView
is NOT rendered as a simpleView
, RNGH buttons in a Modal in Android will work. I created a pull request #1493 that fixes it.
2023, problem is still there, but this worked. Thanks!
I got this working using the suggestion for Library authors
<Modal> <GestureHandlerRootView style={{width:'100%', height:'100%'}}> <myGestureEnabledComponent/> </GestureHandlerRootView> </Modal>
Only tested on my Pixel 5 so far, but things are looking good so far
Works for nexus5x emulator.
not worked when using stack of react-navigation
Thanks its working for me
Thanks its working for me
Thanks for summarising @Goowwy . Works like a charm in Android modal! You all are life savers!