PanGestureHandler not firing events when used with react-native's Animated.View that has got absolute positioning
See original GitHub issueDescription
When PanGestureHandler
is used with react-native
’s Animated.View
that has got absolute positioning, the events are not firing for Android. (On the other hand for iOS and Web, events are firing without any problems.)
This seems resembling issues 1245 and 1168 but I believe this can be treated as a separate issue. (Not related with modals but related with usage with absolute positioning.)
Screenshots
(Not needed)
Steps To Reproduce
With a blank expo project following steps produce the problem. Or alternatively this snack has the exact same problem.
expo init pan-gesture-handler-event-test
cd pan-gesture-handler-event-test
expo install react-native-gesture-handler
- Use
PanGestureHandler
withreact-native
’sAnimated.View
that has absolute positioning. (Minimal code example below has a ready version forApp.js
Expected behavior
Both iOS and Android should fire events and hence should log to console the event translation values.
Actual behavior
For iOS the logging works as expected. But for Android the events are not fired so console log is not received.
Snack or minimal code example
Snack: https://snack.expo.dev/@mehmetkaplan/pan-gesture-handler-event-test
Minimal code example (App.js
):
import * as React from 'react';
import { Text, View, Animated } from 'react-native';
import {
GestureHandlerRootView,
PanGestureHandler,
State,
} from 'react-native-gesture-handler';
export default function App() {
return (
<>
<Text>{" "}</Text>
<Text>{" "}</Text>
<Text>{" "}</Text>
<Text>{" "}</Text>
<Text>{" "}</Text>
<GestureHandlerRootView key={`GHRV}`}>
<PanGestureHandler
key={`PGH`}
onGestureEvent={(e) => {
console.log(`onGestureEvent event.nativeEvent.translationX: ${e.nativeEvent.translationX}`);
}}
onHandlerStateChange={(e) => {
console.log(`onHandlerStateChange event.nativeEvent.translationX: ${e.nativeEvent.translationX}`);
}}
maxPointers={1}
minDist={10}>
<View>
<Animated.View
style={[
{
flex: 1,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
borderWidth: 0,
opacity: 1,
}
]}
useNativeDriver={true}>
<View
style={{
flex: 1,
height: '100%',
width: '100%',
borderRadius: 40,
alignItems: 'center',
justifyContent: 'center',
borderColor: 'gainsboro',
borderWidth: 2,
opacity: 0.9,
overflow: 'hidden',
}}
renderToHardwareTextureAndroid={true}
shouldRasterizeIOS={true}>
<Text>{' DRAG ME \n CHECK CONSOLE LOG\n IT IS NORMAL THAT I DON\'T MOVE\n INTENTION IS TO SEE IF\n EVENTS ARE FIRED'}</Text>
</View>
</Animated.View>
</View>
</PanGestureHandler>
</GestureHandlerRootView>
</>
);
}
Package versions
- React: 17.0.1
- React Native: 0.64.3
- React Native Gesture Handler: ~2.1.0
From package.json
{
"dependencies": {
"expo": "~44.0.0",
"expo-status-bar": "~1.2.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-native": "0.64.3",
"react-native-gesture-handler": "~2.1.0",
"react-native-web": "0.17.1"
}
}
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (2 by maintainers)
Top GitHub Comments
This is working as intended. RNGH uses
GestureHandlerRootView
in order to intercept touch events coming from the native system. Those gestures can be only intercepted if this view is “hit” by a touch event, i.e. this view’s surface has to span the entire touchable area.Normally, when using it in the app you have interactive components contained inside of it. Those child components expand the height of RNGH root view. Using
position: "absolute"
removes the child from the layout flow and allows parent to keep the smallest possible height. This can be observed here in the code below (Layouting examples).The correct thing to do is to fill the entire screen with this component. If you’re using a lot of absolute positioning you may use additional “absolute” root view for convenience, like:
Keep in mind that gesture interactions (waitFor, etc) won’t work across RNGH root views.
Layouting examples
position: "relative"
- defaultposition: "absolute"
After a retry, it seems
style={{ flex: 1 }}
is working. (I guess it failed in the first try because of a problem in hot-reloading, but this is an irrelevant issue for this thread.)On the other hand, this time it is breaking the style chain in the main code. I did a workaround of a combination of both using
style={{ flex: 1 }}
and taking the inner Animated.View to out of GestureHandlerRootView to keep the previous style chain.What I mean is, this chain:
is replaced by this chain:
Anyhow, for my case I am able to continue now. But of course to accept this as a bug needs to be decided by software-mansion. So I am intentionally not closing the issue…
Thank you @j-piasecki for the guidance.