Skip to main content

Working with Gestures and Touch

1. Using Pressable Component

The Pressable component in Expo provides a flexible way to handle touch interactions and gestures. It wraps any content and allows you to define handlers for various press events.

Property Description Values
onPress Function called when the press is released function
onLongPress Function called when the press is held for a long time function
onPressIn Function called when the press begins function
onPressOut Function called when the press ends function
android_ripple Configuration for Android ripple effect object
style Styling for the component style

Example: Basic Pressable Usage

<Pressable
  onPress={() => console.log("Pressed")}
  onPressIn={() => console.log("Press started")}
  onPressOut={() => console.log("Press ended")}
>
  <Text>Tap Me</Text>
</Pressable>

Example: Pressable with Ripple Effect (Android)

<Pressable
  android_ripple={{ color: "#ff0000" }}
  onPress={() => console.log("Ripple effect pressed")}
>
  <Text>Press with Ripple</Text>
</Pressable>

2. Handling Press Events

Event Description Properties
onPress Triggered when the user presses and releases the component event object with nativeEvent
onLongPress Triggered when the user presses and holds for a set duration event object with nativeEvent
onPressIn Triggered when the user presses down on the component event object with nativeEvent
onPressOut Triggered when the user releases the press on the component event object with nativeEvent

Example: Basic Press Event

<Pressable
  onPress={() => console.log('Pressed!')}
  style={({ pressed }) => [
    styles.button,
    { backgroundColor: pressed ? '#ff0000' : '#00ff00' }
  ]}
>
  <Text>Press Me</Text>
</Pressable>

Example: Long Press Event

<Pressable
  onLongPress={() => console.log('Long pressed!')}
  style={styles.button}
>
  <Text>Press and Hold</Text>
</Pressable>
Note: Pressable is the recommended component for handling press events in Expo, as it provides better accessibility and gesture support than TouchableOpacity.

3. Using Gesture Handler

Example: Basic Tap Gesture

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

const tapGesture = Gesture.Tap()
  .onEnd((event) => {
    console.log('Tap recognized');
  });

export default function App() {
  return (
    <GestureDetector gesture={tapGesture}>
      <TouchableOpacity style={{ flex: 1 }}>
        <Text>Tap me</Text>
      </TouchableOpacity>
    </GestureDetector>
  );
}
Gesture Description Properties
Gesture.Tap Recognizes a tap gesture numberOfTaps, tappingThreshold
Gesture.Pan Recognizes pan (drag) gestures minDistance, activeOffsetX, activeOffsetY
Gesture.LongPress Recognizes long press gestures minDuration, maxDistance
Gesture.Simultaneous Allows multiple gestures to be recognized simultaneously gestures
Gesture.Exclusive Ensures only one gesture is recognized at a time gestures
Note: Gesture Handler requires native modules and must be properly linked in your Expo project.
Warning: On Android, you must add android:hardwareAccelerated="true" to your AndroidManifest.xml.

Gesture Handler Setup

  • Install react-native-gesture-handler
  • Add <GestureHandlerRootView> at the root of your app
  • Link native modules (via Expo)

4. Implementing Pan Gestures

Property Description Values
onPanGestureEvent Callback function triggered during pan gesture function
onPanStateChange Callback function triggered when pan state changes function
activeOffsetX Active offset for X axis number
activeOffsetY Active offset for Y axis number
failOffsetX Fail offset for X axis number
failOffsetY Fail offset for Y axis number

Example: Basic Pan Gesture

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

PanGestureHandler
  .onPanGestureEvent((event) => {
    console.log('Pan offset X: ', event.nativeEvent.translationX);
    console.log('Pan offset Y: ', event.nativeEvent.translationY);
  })
  .onPanStateChange((event) => {
    if (event.nativeEvent.state === 1) {
      console.log('Pan started');
    } else if (event.nativeEvent.state === 3) {
      console.log('Pan ended');
    }
  });

5. Using Tap Gestures

Property Description Values
onPress Callback function when the touch is released function
onLongPress Callback function when the touch is held for a long time function
onPressIn Callback function when the touch begins function
onPressOut Callback function when the touch ends function

Example: Basic Tap Gesture

<TouchableOpacity onPress=&#x27;() => console.log("Tapped")&#x27;>
  <Text>Press Me</Text>
</TouchableOpacity>

Example: Long Press Gesture

<TouchableOpacity onLongPress=&#x27;() => console.log("Long Pressed")&#x27;>
  <Text>Press and Hold</Text>
</TouchableOpacity>

6. Implementing Swipe Gestures

Property Description Values
swipeDirection Direction of the swipe gesture "left", "right", "up", "down"
threshold Minimum distance in pixels to recognize a swipe 50
velocityThreshold Minimum velocity in pixels per second to recognize a swipe 1000

Example: Swipe Gesture Handler

import { GestureDetector } from 'react-native-gesture-handler';<br><br>const SwipeExample = () => {<br>  const swipeHandler = Gesture.Swipe()<br>    .setMinDistance(50)<br>    .setVelocityThreshold(1000)<br>    .onEnd((event) => {<br>      if (event.velocityX < 0) {<br>        console.log('Swiped left');<br>      } else {<br>        console.log('Swiped right');<br>      }<br>    });<br><br>  return (<br>    <GestureDetector gesture={swipeHandler}><br>      <View style={{ width: 200, height: 200, backgroundColor: 'lightblue' }} /><br>    </GestureDetector><br>  );<br>};
Note: The react-native-gesture-handler library is required for swipe gestures.

7. Using Pinch Gestures

Property Description Values
pinchEnabled Enables or disables pinch gesture handling true | false
onPinchEvent Callback function triggered on pinch gesture changes Function with event parameter
pinchSensitivity Sensitivity of the pinch gesture recognition number (0.1 - 1.0)

Example: Basic Pinch Gesture Setup

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

const handlePinch = (event) => {
  console.log('Scale:', event.scale);
};

<PinchGestureHandler
  onGestureEvent={handlePinch}
  pinchSensitivity={0.5}
>
  <View style={{ width: 200, height: 200 }}>
    <Image source={require('./image.jpg')} style={{ flex: 1 }} />
  </View>
</PinchGestureHandler>
Note: The pinchSensitivity property allows fine-tuning of how sensitive the gesture handler is to pinch movements.
Warning: Ensure that the view being pinched has a defined size or layout constraints to prevent unexpected behavior.

8. Creating Rotation Gestures

Property Description Values
rotation Rotation angle in degrees number
originX Horizontal origin point for rotation number
originY Vertical origin point for rotation number

Example: Basic Rotation Gesture

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

const rotationGesture = Gesture.Rotation()
  .onUpdate((event) => {
    console.log('Rotation:', event.rotation);
  });

export default function RotationExample() {
  return (
    <View style={styles.container}>
      <GestureHandlerRootView style={styles.container}>
        <TouchableOpacity
          style={styles.box}
          onPress={rotationGesture}
        >
          <Text>Rotate Me</Text>
        </TouchableOpacity>
      </GestureHandlerRootView>
    </View>
  );
}
Note: The rotation gesture can be combined with other gestures for complex interactions.

9. Combining Gestures

Example: Combining Tap and Long Press

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

const tap = Gesture.Tap().numberOfTaps(1);
const longPress = Gesture.LongPress().minDuration(500);

const combinedGesture = Gesture.Exclusive(tap, longPress);

export default function CombinedGestures() {
  return (
    <GestureDetector gesture={combinedGesture}>
      <View style={styles.box} />
    </GestureDetector>
  );
}
Gesture Description Usage
Gesture.Exclusive() Only one gesture is recognized at a time Use for mutually exclusive gestures
Gesture.Simultaneous() Gestures can be recognized at the same time Use for overlapping gestures like pan + tap
Gesture.Race() First gesture to start is recognized Use for fallbacks or alternatives
Note: Exclusive gestures prevent conflicts, while simultaneous gestures allow multiple interactions to occur at once.

Gesture Combination Strategies

  • Exclusive: One gesture at a time, no overlap
  • Simultaneous: All gestures can fire together
  • Race: First gesture wins, others ignored

10. Using Touch Events

Event Type Description Properties
onTouchStart Triggered when a touch begins on the element nativeEvent, touches
onTouchMove Triggered when a touch moves on the element nativeEvent, touches
onTouchEnd Triggered when a touch ends on the element nativeEvent, touches

Example: Basic Touch Event Handler

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

const TouchHandler = () => {
  const handleTouchStart = (e) => {
    console.log('Touch started:', e.nativeEvent.touches);
  };

  return (
    <View
      onTouchStart={handleTouchStart}
      style={{ width: 200, height: 200, backgroundColor: 'lightblue' }}
    >
      <Text>Touch me</Text>
    </View>
  );
};

export default TouchHandler;
Note: Touch events in Expo are handled similarly to React Native, but with additional support for gesture handling via react-native-gesture-handler.

11. Creating Gesture Composables

Property Description Example
useGesture Hook to create custom gesture handlers const gesture = useGesture(() => ({
onStart Callback when gesture starts onStart: (event) => console.log('Started')
onMove Callback when gesture moves onMove: (event) => console.log('Moved')
onEnd Callback when gesture ends onEnd: (event) => console.log('Ended')

Example: Basic Gesture Composable

import { useGesture } from 'react-native-gesture-handler';\n\nconst MyGesture = () => {\n  const gesture = useGesture({\n    onStart: (event) => console.log('Started'),\n    onMove: (event) => console.log('Moved'),\n    onEnd: (event) => console.log('Ended')\n  });\n\n  return (\n    <TouchableOpacity gesture={gesture}>\n      <Text>Press Me</Text>\n    </TouchableOpacity>\n  );\n};
Note: Gesture composable hooks should be used inside components that support gesture handling, such as TouchableOpacity or View with gesture prop.
Warning: Make sure to properly handle gesture state transitions to avoid unexpected behavior or performance issues.

12. Handling Double Tap

Property Description Values
onDoubleTap Callback function triggered when a double tap is detected function

Example: Double Tap Handler

import { TouchableOpacity } from 'react-native';

<TouchableOpacity
  onDoubleTap={() => console.log('Double tap detected')}
  style={styles.button}
>
  <Text>Double Tap Me</Text>
</TouchableOpacity>
Note: The onDoubleTap property is not part of the standard React Native API. It's a custom implementation or provided by libraries like react-native-gesture-handler.

Was this article helpful?