7

I am trying to practice using react-native-gesture-handler. Everything renders but I am unable to move a square around the screen. I have installed react-native-reanimated, the appropriate plugin, cleared the cache and installed react-native-gesture-handler using expo, but it does not work on my android phone or android emulator. Interestingly it does work on the web browser. The following is the code:

import {
    PanGestureHandler,
    PanGestureHandlerGestureEvent,
} from "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import Animated, {
    useAnimatedGestureHandler,
    useAnimatedStyle,
    useSharedValue,
    withSpring,
} from "react-native-reanimated";

const SIZE = 100.0;
const CIRCLE_RADIUS = SIZE * 2;

type ContextType = {
    translateX: number;
    translateY: number;
};

export default function App() {
    const translateX = useSharedValue(0);
    const translateY = useSharedValue(0);

    const panGestureEvent = useAnimatedGestureHandler<
        PanGestureHandlerGestureEvent,
        ContextType
    >({
        onStart: (event, context) => {
            context.translateX = translateX.value;
            context.translateY = translateY.value;
        },
        onActive: (event, context) => {
            translateX.value = event.translationX + context.translateX;
            translateY.value = event.translationY + context.translateY;
        },
        onEnd: () => {
            const distance = Math.sqrt(translateX.value ** 2 + translateY.value ** 2);

            if (distance < CIRCLE_RADIUS + SIZE / 2) {
                translateX.value = withSpring(0);
                translateY.value = withSpring(0);
            }
        },
    });

    const rStyle = useAnimatedStyle(() => {
        return {
            transform: [
                {
                    translateX: translateX.value,
                },
                {
                    translateY: translateY.value,
                },
            ],
        };
    });

    return (
        <View style={styles.container}>
            <View style={styles.circle}>
                <PanGestureHandler onGestureEvent={panGestureEvent}>
                    <Animated.View style={[styles.square, rStyle]} />
                </PanGestureHandler>
            </View>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "center",
        justifyContent: "center",
    },
    square: {
        width: SIZE,
        height: SIZE,
        backgroundColor: "rgba(0, 0, 256, 0.5)",
        borderRadius: 20,
    },
    circle: {
        width: CIRCLE_RADIUS * 2,
        height: CIRCLE_RADIUS * 2,
        alignItems: "center",
        justifyContent: "center",
        borderRadius: CIRCLE_RADIUS,
        borderWidth: 5,
        borderColor: "rgba(0, 0, 256, 0.5)",
    },
});

Why will it not work on my Android device or Android emulator but works on the web browser? Do I need to install something else? Thank you in advance!

Solution: if you're using React Native CLI you must wrap the Root Component with the GestureHandlerRootView component (from react-native-gesture-handler). For my situation the following update is needed:

<GestureHandlerRootView style={styles.container}>
           <View style={styles.circle}>
                <PanGestureHandler onGestureEvent={panGestureEvent}>
                    <Animated.View style={[styles.square, rStyle]} />
                </PanGestureHandler>
            </View>
<GestureHandlerRootView />
arec
  • 91
  • 1
  • 5
  • 6
    Solution: if you're using React Native CLI you must wrap the Root Component with the GestureHandlerRootView component (from react-native-gesture-handler). For my situation the following update is needed: – arec Dec 20 '21 at 09:50
  • Man, you are a lifesaver. Thanks a lot. I have been having this issue for over a week. – Vivek Makwana Dec 24 '21 at 09:25
  • 2
    This solution works not only on "bare" workflows but also on "managed" (expo) workflows. – Daniel Loureiro Feb 04 '22 at 03:00

2 Answers2

4

To get it work on Android you have to wrap the entry point of your app with <GestureHandlerRootView> component and import it from 'react-native-gesture-handler'

Muneeb Ejaz
  • 696
  • 6
  • 11
0

As it was recommended in RNGH documentation, you can wrap your wanted component with gestureHandlerRootHOC:

const ExampleWithHoc = gestureHandlerRootHOC(() => (
  <View>
    <DraggableBox />
  </View>
  );
);


export default function Example() {
  return (
    <Modal>
      <ExampleWithHoc />
    </Modal>
  );
}