question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

PanGestureHandler not firing events when used with react-native's Animated.View that has got absolute positioning

See original GitHub issue

Description

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.

  1. expo init pan-gesture-handler-event-test
  2. cd pan-gesture-handler-event-test
  3. expo install react-native-gesture-handler
  4. Use PanGestureHandler with react-native’s Animated.View that has absolute positioning. (Minimal code example below has a ready version for App.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:closed
  • Created 2 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
jakub-gonetcommented, Feb 22, 2022

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:

import React, {useState} from 'react';
import {Text, View, Animated} from 'react-native';
import {
  GestureHandlerRootView,
  PanGestureHandler,
} from 'react-native-gesture-handler';

export default function App() {
  const [{width, height}, setDims] = useState({width: 0, height: 0});
  return (
    <>
      <GestureHandlerRootView style={{width, height}}>
        <PanGestureHandler
          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}>
          <Animated.View
            onLayout={({nativeEvent: {layout}}) => {
              setDims({width: layout.width, height: layout.height});
            }}
            style={[
              {
                position: 'absolute',
                alignItems: 'center',
                justifyContent: 'center',
              },
            ]}
            useNativeDriver={true}>
            <View
              style={{
                borderWidth: 2,
              }}>
              <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>
        </PanGestureHandler>
      </GestureHandlerRootView>
    </>
  );
}

Keep in mind that gesture interactions (waitFor, etc) won’t work across RNGH root views.

Layouting examples

position: "relative" - default

import * as React from 'react';
import {View} from 'react-native';

export default function App() {
  return (
    <>
      <View style={{backgroundColor: 'pink'}}>
        <View style={{backgroundColor: 'lightblue', width: 200, height: 200}} />
      </View>
    </>
  );
}

position: "absolute"

import * as React from 'react';
import {View} from 'react-native';

export default function App() {
  return (
    <>
      <View style={{backgroundColor: 'pink'}}>
        <View
          style={{
            backgroundColor: 'lightblue',
            width: 200,
            height: 200,
            position: 'absolute',
          }}
        />
      </View>
    </>
  );
}
2reactions
MehmetKaplancommented, Dec 29, 2021

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:

<GestureHandlerRootView ...>
    <PanGestureHandler ...>
        <Animated.View ...>

is replaced by this chain:

<Animated.View ...>
    <GestureHandlerRootView style={{ flex: 1, width: '100%', height: '100%' }} ...>
        <PanGestureHandler ...>

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React Native - PanGestureHandler does not work after ...
It seems to work when I store the value of translateX and translateY in the state, however, it resets the position after the...
Read more >
PanGestureHandler | React Native Gesture Handler
Gesture callback can be used for continuous tracking of the pan gesture. ... finger changes you can use relative or absolute position provided...
Read more >
Introduction to Gesture Handler 2 (React Native) - YouTube
In this tutorial we'll learn how to handle the new APIs of react - native -gesture-handler.This tutorial is the first of a new...
Read more >
Events | React Native Reanimated
Now all we have to do is to use the useAnimatedStyle hook in order to map the pressed shared value state to the...
Read more >
Building a Draggable Sheet with React Native Reanimated 2
The sliding aspect takes advantage of the familiar swipe gesture, allowing the user to quickly show or hide content. Whereas drawers may be...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found