Skip to main content

Using React Native Gesture Handler

1. Installing Gesture Handler

React Native Gesture Handler is a library that provides native gesture recognition for React Native applications. It allows you to handle complex gestures like pan, pinch, and rotation with high performance.

Step Description Command
1 Install the Gesture Handler library using npm or yarn npm install react-native-gesture-handler
2 For iOS, run pod install to link native dependencies npx pod-install
Note: Make sure to follow the setup instructions for both iOS and Android platforms as outlined in the official documentation.

Example: Basic Setup

import 'react-native-gesture-handler'; // Must be imported at the top of your app entry point

// Example usage in a component
import { PanGestureHandler } from 'react-native-gesture-handler';

<PanGestureHandler>
  <View style={styles.box} />
</PanGestureHandler>

2. Using Tap Gesture Handler

Property Description Default Notes
numberOfTaps Number of taps required to trigger the handler 1 Can be 1 or 2 for double tap
maxDurationMs Maximum duration in milliseconds to consider a tap 500 Used to detect quick taps
minPointers Minimum number of pointers (fingers) required to trigger the handler 1 Can be 1 or more for multi-touch support
maxDist Maximum distance in pixels that the pointer can move to still be considered a tap 50 Prevents movement from being interpreted as a tap

Example: Basic Tap Gesture Handler

import { TapGestureHandler } from 'react-native-gesture-handler';

<TapGestureHandler
  numberOfTaps={1}
  maxDurationMs={500}
  maxDist={50}
>
  <View style={styles.button}>
    <Text>Tap Me</Text>
  </View>
</TapGestureHandler>

Example: Double Tap Gesture Handler

import { TapGestureHandler } from 'react-native-gesture-handler';

<TapGestureHandler
  numberOfTaps={2}
  maxDurationMs={300}
>
  <View style={styles.doubleTapArea}>
    <Text>Double Tap</Text>
  </View>
</TapGestureHandler>
Note: The maxDist property is useful for ensuring that a user's slight movement (e.g., shaking the finger) doesn't count as a tap.

3. Using Pan Gesture Handler

Property Description Default Notes
onGestureEvent Callback function for gesture events null Used to handle pan movement and update state
onHandlerStateChange Callback for handler state changes (BEGIN, END, etc.) null Useful for detecting when gesture starts or ends
activeOffsetX Active offset for X axis (in pixels) 0 Minimum movement before gesture is considered active
activeOffsetY Active offset for Y axis (in pixels) 0 Minimum movement before gesture is considered active
failOffsetX Fail offset for X axis (in pixels) 0 If movement exceeds this, gesture fails
failOffsetY Fail offset for Y axis (in pixels) 0 If movement exceeds this, gesture fails

Example: Basic Pan Gesture Handler

import React, { useRef } from 'react';
import { View } from 'react-native';
import { PanGestureHandler, State } from 'react-native-gesture-handler';

const PanExample = () => {
  const translationX = useRef(new Animated.Value(0)).current;
  const translationY = useRef(new Animated.Value(0)).current;

  const onGestureEvent = Animated.event([
    { nativeEvent: { translationX: translationX } },
    { nativeEvent: { translationY: translationY } }
  ], { useNativeDriver: true });

  const onHandlerStateChange = (event) => {
    if (event.nativeEvent.state === State.END) {
      translationX.setValue(0);
      translationY.setValue(0);
    }
  };

  return (
    <PanGestureHandler
      onGestureEvent={onGestureEvent}
      onHandlerStateChange={onHandlerStateChange}
    >
      <Animated.View
        style={[
          styles.box,
          {
            transform: [
              { translateX: translationX },
              { translateY: translationY }
            ]
          }
        ]}
      >
      </Animated.View>
    </PanGestureHandler>
  );
};

const styles = StyleSheet.create({
  box: {
    width: 100,
    height: 100,
    backgroundColor: 'blue',
    borderRadius: 10
  }
});
Note: The Animated.event is used to map gesture properties to animated values. Ensure that useNativeDriver is set to true for better performance.
Warning: Make sure to properly handle the State.END event to reset the animated values if needed, otherwise the component might not behave as expected.

4. Using Pinch Gesture Handler

Property Description Default Notes
enabled Enables or disables the pinch gesture handler true Set to false to disable the gesture
minScale Minimum scale factor allowed for the pinch gesture 0.5 Value must be greater than 0
maxScale Maximum scale factor allowed for the pinch gesture 3.0 Value must be greater than minScale
onGestureEvent Callback function for gesture events null Used to update animated values during the gesture
onHandlerStateChange Callback function for handler state changes null Used to handle gesture start and end events

Example: Basic Pinch Gesture Handler

import { PinchGestureHandler, State } from 'react-native-gesture-handler';
import Animated, { useAnimatedRef, useAnimatedStyle } from 'react-native-reanimated';

const PinchExample = () => {
  const scale = useSharedValue(1);
  const animatedRef = useAnimatedRef();

  const onGestureEvent = event => {
    scale.value = event.nativeEvent.scale;
  };

  const onHandlerStateChange = event => {
    if (event.nativeEvent.oldState === State.BEGAN) {
      scale.value = 1;
    }
  };

  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [{ scale: scale.value }],
    };
  });

  return (
    <PinchGestureHandler
      onGestureEvent={onGestureEvent}
      onHandlerStateChange={onHandlerStateChange}>
      <Animated.View style={[animatedStyle, { width: 200, height: 200 }]}>
        <View style={{ backgroundColor: 'blue', width: '100%', height: '100%' }} />
      </Animated.View>
    </PinchGestureHandler>
  );
};
Note: The PinchGestureHandler requires a child component that is an Animated.View or similar animated component to apply transformations.
Warning: Ensure that the scale value is clamped between minScale and maxScale to prevent unexpected behavior.

5. Using Rotation Gesture Handler

Property Description Default Notes
rotation Rotation angle in radians 0 Read-only value, updated by gesture
onGestureEvent Callback for gesture updates null Used to update animated values
onEnd Callback when gesture ends null Triggers after rotation completes

Example: Rotation Gesture Handler

import { RotationGestureHandler, State } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';

const rotation = useSharedValue(0);

const animatedStyle = useAnimatedStyle(() => {
  return {
    transform: [{ rotate: rotation.value + 'rad' }]
  };
});

const onGestureEvent = (event) => {
  rotation.value = event.nativeEvent.rotation;
};

const onHandlerStateChange = (event) => {
  if (event.nativeEvent.state === State.END) {
    rotation.value = 0;
  }
};

<RotationGestureHandler
  onGestureEvent={onGestureEvent}
  onHandlerStateChange={onHandlerStateChange}>
  <Animated.View style={animatedStyle}>
    <View style={{ width: 100, height: 100, backgroundColor: 'blue' }} />
  </Animated.View>
</RotationGestureHandler>
Note: The rotation value is in radians. For degrees, multiply by 180 / Math.PI.
Warning: Ensure that the rotation value is reset on gesture end to prevent accumulation.

6. Combining Multiple Gestures

React Native Gesture Handler allows combining multiple gestures into complex touch interactions. This is achieved using gesture composition methods like gesture1.andThen(gesture2), gesture1.orElse(gesture2), and gesture1.exclusive(gesture2).

Gestures Composition Method Description
PanGesture andThen() Executes gesture2 only after gesture1 completes successfully.
TapGesture orElse() Triggers gesture2 if gesture1 fails to recognize.
LongPressGesture exclusive() Prevents gesture2 from starting if gesture1 is active.

Example: Combining Pan and Tap Gestures

import { PanGestureHandler, TapGestureHandler } from 'react-native-gesture-handler';\n\nconst panGesture = PanGestureHandler.create({\n  minDist: 10,\n  maxPointers: 1\n});\n\nconst tapGesture = TapGestureHandler.create({\n  maxDuration: 200,\n  minPointers: 1\n});\n\nconst combinedGesture = panGesture.andThen(tapGesture);\n\n// Usage in component\n<PanGestureHandler gesture={combinedGesture}>\n  <View>...</View>\n</PanGestureHandler>

Example: Exclusive Long Press and Pan

import { LongPressGestureHandler, PanGestureHandler } from 'react-native-gesture-handler';\n\nconst longPress = LongPressGestureHandler.create({\n  minDuration: 500\n});\n\nconst pan = PanGestureHandler.create({\n  minDist: 10\n});\n\nconst exclusiveGesture = longPress.exclusive(pan);\n\n// Usage in component\n<LongPressGestureHandler gesture={exclusiveGesture}>\n  <View>...</View>\n</LongPressGestureHandler>

7. Handling Gesture State

State Description Values
BEGAN Gesture has started BEGAN
FAILED Gesture has failed to recognize FAILED
ACTIVE Gesture is active and recognized ACTIVE
END Gesture has ended END
CANCELLED Gesture was cancelled CANCELLED

Example: Using State in Gesture Handler

import { State } from 'react-native-gesture-handler';

const handleGestureStateChange = (event) => {
  const { state } = event.nativeEvent;
  switch (state) {
    case State.BEGAN:
      console.log('Gesture started');
      break;
    case State.ACTIVE:
      console.log('Gesture active');
      break;
    case State.END:
      console.log('Gesture ended');
      break;
    case State.CANCELLED:
      console.log('Gesture cancelled');
      break;
  }
};

8. Using Fling Gesture Handler

Property Description Default Notes
fling Enables fling gesture recognition false Set to true to enable fling gestures
direction Direction of the fling gesture Directions.RIGHT One of RIGHT, LEFT, UP, or DOWN
threshold Minimum velocity threshold to recognize a fling 0.5 Velocity in pixels per second
vibration Whether to vibrate on gesture recognition false Set to true to enable vibration feedback

Example: Fling Gesture Handler Setup

import { Fling } from 'react-native-gesture-handler';

<Fling
  direction={Fling.Directions.RIGHT}
  threshold={0.5}
  onGestureEvent={(event) => {
    console.log('Fling detected:', event.nativeEvent);
  }}
>
  <View style={styles.box}></View>
</Fling>
Note: The Fling gesture handler is ideal for swipe-based navigation or list interactions where a quick directional swipe should trigger an action.

9. Implementing Gesture Callbacks

Callback Description Parameters Notes
onStart Called when the gesture starts gestureState Initial state of the gesture
onActive Called when the gesture becomes active gestureState Updated state during gesture
onEnd Called when the gesture ends gestureState Final state of the gesture
onFail Called when the gesture fails to activate gestureState Gesture did not meet activation criteria
onCancel Called when the gesture is cancelled gestureState Gesture was interrupted

Example: Handling Gesture Callbacks

import { Gesture } from 'react-native-gesture-handler';

const gesture = Gesture.Tap()
  .onStart((event) => {
    console.log('Gesture started');
  })
  .onActive((event) => {
    console.log('Gesture active');
  })
  .onEnd((event) => {
    console.log('Gesture ended');
  });

10. Integrating with Reanimated

React Native Gesture Handler and Reanimated can be used together to create complex, performant animations that respond to user gestures. This integration allows for smooth, native-like interactions.

Feature Description Usage
PanGestureHandler Handles pan gestures for drag interactions. const pan = Gesture.Pan().onUpdate((e) => { ... });
Reanimated Used for declarative animations and gesture-based state updates. useAnimatedStyle(() => { ... })

Example: Pan Gesture with Reanimated

import { PanGestureHandler } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';

const translateX = useSharedValue(0);
const translateY = useSharedValue(0);

const pan = Gesture.Pan()
  .onUpdate((e) => {
    translateX.value = e.translationX;
    translateY.value = e.translationY;
  })
  .onEnd(() => {
    translateX.value = 0;
    translateY.value = 0;
  });

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

<PanGestureHandler gesture={pan}>
  <Animated.View style={animatedStyle}>
    <View style={{ width: 100, height: 100, backgroundColor: 'blue' }} />
  </Animated.View>
</PanGestureHandler>
Note: Ensure that react-native-gesture-handler and react-native-reanimated are properly linked and configured in your project.
Warning: Reanimated requires specific setup in babel.config.js and index.js to function correctly.

Was this article helpful?