Declarative API exposing platform native touch and gesture system to React Native
—
Comprehensive event types and payload structures for handling gesture interactions with detailed coordinate and timing information.
Base event types used throughout the gesture handling system.
/**
* Basic gesture event structure
* Contains native event data with handler and state information
*/
interface GestureEvent<T = Record<string, unknown>> {
nativeEvent: T & {
handlerTag: number;
numberOfPointers: number;
state: number;
};
}
/**
* Handler state change event structure
* Fired when gesture handler changes state (begin, active, end, etc.)
*/
interface HandlerStateChangeEvent<T = Record<string, unknown>> {
nativeEvent: T & {
handlerTag: number;
numberOfPointers: number;
state: number;
oldState: number;
};
}Event types used with the new Gesture API (GestureDetector and Gesture factory).
/**
* Update event for the modern Gesture API
* Provides real-time gesture data during interaction
*/
interface GestureUpdateEvent<T = Record<string, unknown>> {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
handlerTag: number;
numberOfPointers: number;
state: number;
} & T;
/**
* State change event for the modern Gesture API
* Fired when gesture state transitions occur
*/
interface GestureStateChangeEvent<T = Record<string, unknown>> {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
handlerTag: number;
numberOfPointers: number;
state: number;
oldState: number;
} & T;Advanced touch event types providing detailed touch information.
/**
* Touch event with multiple pointer support
* Contains detailed information about all active touches
*/
interface GestureTouchEvent {
handlerTag: number;
numberOfTouches: number;
state: number;
eventType: number;
allTouches: TouchData[];
changedTouches: TouchData[];
}
/**
* Individual touch data
* Detailed information about a single touch point
*/
interface TouchData {
id: number;
x: number;
y: number;
absoluteX: number;
absoluteY: number;
force?: number;
timestamp: number;
}Events specific to tap gesture interactions.
/**
* Tap gesture event payload
* Contains position information for tap gestures
*/
interface TapGestureHandlerEventPayload {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
}
// Complete tap gesture event types
type TapGestureHandlerGestureEvent = GestureEvent<TapGestureHandlerEventPayload>;
type TapGestureHandlerStateChangeEvent = HandlerStateChangeEvent<TapGestureHandlerEventPayload>;Events specific to pan/drag gesture interactions.
/**
* Pan gesture event payload
* Contains position, translation, and velocity information
*/
interface PanGestureHandlerEventPayload {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
translationX: number;
translationY: number;
velocityX: number;
velocityY: number;
stylusData?: StylusData;
}
/**
* Pan gesture change event payload (New API)
* Streamlined payload for modern pan gestures
*/
interface PanGestureChangeEventPayload {
translationX: number;
translationY: number;
velocityX: number;
velocityY: number;
}
/**
* Stylus-specific data for supported devices
*/
interface StylusData {
pressure: number;
tiltX: number;
tiltY: number;
twist: number;
}
// Complete pan gesture event types
type PanGestureHandlerGestureEvent = GestureEvent<PanGestureHandlerEventPayload>;
type PanGestureHandlerStateChangeEvent = HandlerStateChangeEvent<PanGestureHandlerEventPayload>;Events specific to pinch/zoom gesture interactions.
/**
* Pinch gesture event payload
* Contains scale factor and focal point information
*/
interface PinchGestureHandlerEventPayload {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
scale: number;
focalX: number;
focalY: number;
velocity: number;
}
/**
* Pinch gesture change event payload (New API)
* Streamlined payload for modern pinch gestures
*/
interface PinchGestureChangeEventPayload {
scale: number;
focalX: number;
focalY: number;
velocity: number;
}
// Complete pinch gesture event types
type PinchGestureHandlerGestureEvent = GestureEvent<PinchGestureHandlerEventPayload>;
type PinchGestureHandlerStateChangeEvent = HandlerStateChangeEvent<PinchGestureHandlerEventPayload>;Events specific to rotation gesture interactions.
/**
* Rotation gesture event payload
* Contains rotation angle and anchor point information
*/
interface RotationGestureHandlerEventPayload {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
rotation: number; // in radians
anchorX: number;
anchorY: number;
velocity: number;
}
// Complete rotation gesture event types
type RotationGestureHandlerGestureEvent = GestureEvent<RotationGestureHandlerEventPayload>;
type RotationGestureHandlerStateChangeEvent = HandlerStateChangeEvent<RotationGestureHandlerEventPayload>;Events specific to long press gesture interactions.
/**
* Long press gesture event payload
* Contains position and duration information
*/
interface LongPressGestureHandlerEventPayload {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
duration: number; // in milliseconds
}
// Complete long press gesture event types
type LongPressGestureHandlerGestureEvent = GestureEvent<LongPressGestureHandlerEventPayload>;
type LongPressGestureHandlerStateChangeEvent = HandlerStateChangeEvent<LongPressGestureHandlerEventPayload>;Events specific to fling/swipe gesture interactions.
/**
* Fling gesture event payload
* Contains position information for fling gestures
*/
interface FlingGestureHandlerEventPayload {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
}
// Complete fling gesture event types
type FlingGestureHandlerGestureEvent = GestureEvent<FlingGestureHandlerEventPayload>;
type FlingGestureHandlerStateChangeEvent = HandlerStateChangeEvent<FlingGestureHandlerEventPayload>;Events specific to force touch gesture interactions (deprecated feature).
/**
* Force touch gesture event payload (deprecated)
* Contains position and force information
* @deprecated Force touch is deprecated
*/
interface ForceTouchGestureHandlerEventPayload {
x: number;
y: number;
absoluteX: number;
absoluteY: number;
force: number; // 0.0 to 1.0
}
/**
* Force touch gesture change event payload (New API, deprecated)
* @deprecated Force touch is deprecated
*/
interface ForceTouchGestureChangeEventPayload {
force: number;
}
// Complete force touch gesture event types
type ForceTouchGestureHandlerGestureEvent = GestureEvent<ForceTouchGestureHandlerEventPayload>;
type ForceTouchGestureHandlerStateChangeEvent = HandlerStateChangeEvent<ForceTouchGestureHandlerEventPayload>;Events specific to native view gesture interactions.
/**
* Native view gesture event payload
* Contains pointer inside/outside information
*/
interface NativeViewGestureHandlerPayload {
pointerInside: boolean;
}
// Complete native view gesture event types
type NativeViewGestureHandlerGestureEvent = GestureEvent<NativeViewGestureHandlerPayload>;
type NativeViewGestureHandlerStateChangeEvent = HandlerStateChangeEvent<NativeViewGestureHandlerPayload>;import React from "react";
import { View, Text } from "react-native";
import { GestureDetector, Gesture } from "react-native-gesture-handler";
function EventHandlingExample() {
const tapGesture = Gesture.Tap()
.onBegin((event) => {
console.log("Tap began at:", event.x, event.y);
})
.onStart((event) => {
console.log("Tap started at:", event.absoluteX, event.absoluteY);
})
.onEnd((event) => {
console.log("Tap ended with state:", event.state);
});
const panGesture = Gesture.Pan()
.onUpdate((event) => {
console.log("Pan translation:", event.translationX, event.translationY);
console.log("Pan velocity:", event.velocityX, event.velocityY);
})
.onEnd((event) => {
console.log("Pan ended with final translation:", event.translationX, event.translationY);
});
return (
<GestureDetector gesture={Gesture.Simultaneous(tapGesture, panGesture)}>
<View style={{ width: 200, height: 200, backgroundColor: "lightblue" }}>
<Text>Tap and Pan Events</Text>
</View>
</GestureDetector>
);
}import React, { useCallback } from "react";
import { View } from "react-native";
import { GestureDetector, Gesture } from "react-native-gesture-handler";
function AdvancedEventProcessing() {
const handlePinchUpdate = useCallback((event: GestureUpdateEvent<PinchGestureChangeEventPayload>) => {
const { scale, focalX, focalY, velocity } = event;
// Process pinch data
console.log(`Pinch: scale=${scale.toFixed(2)}, focal=(${focalX.toFixed(0)}, ${focalY.toFixed(0)})`);
// Apply scale with velocity damping
const dampedScale = scale * (1 - velocity * 0.01);
console.log(`Damped scale: ${dampedScale.toFixed(2)}`);
}, []);
const handleRotationUpdate = useCallback((event: GestureUpdateEvent<RotationGestureChangeEventPayload>) => {
const { rotation, anchorX, anchorY, velocity } = event;
// Convert radians to degrees
const degrees = (rotation * 180) / Math.PI;
console.log(`Rotation: ${degrees.toFixed(1)}°, anchor=(${anchorX.toFixed(0)}, ${anchorY.toFixed(0)})`);
}, []);
const pinchGesture = Gesture.Pinch().onUpdate(handlePinchUpdate);
const rotationGesture = Gesture.Rotation().onUpdate(handleRotationUpdate);
return (
<GestureDetector gesture={Gesture.Simultaneous(pinchGesture, rotationGesture)}>
<View style={{ width: 300, height: 300, backgroundColor: "lightgreen" }} />
</GestureDetector>
);
}import React from "react";
import { View } from "react-native";
import { GestureDetector, Gesture } from "react-native-gesture-handler";
function TouchEventProcessing() {
const panGesture = Gesture.Pan()
.onUpdate((event) => {
// Access basic touch information
console.log(`Touch at: (${event.x}, ${event.y})`);
console.log(`Absolute position: (${event.absoluteX}, ${event.absoluteY})`);
console.log(`Number of pointers: ${event.numberOfPointers}`);
// Pan-specific data
if ('translationX' in event && 'translationY' in event) {
console.log(`Translation: (${event.translationX}, ${event.translationY})`);
console.log(`Velocity: (${event.velocityX}, ${event.velocityY})`);
}
});
return (
<GestureDetector gesture={panGesture}>
<View style={{ width: 200, height: 200, backgroundColor: "orange" }} />
</GestureDetector>
);
}Understanding gesture states is crucial for proper event handling:
import { State } from "react-native-gesture-handler";
function handleStateChange(event: GestureStateChangeEvent) {
switch (event.state) {
case State.UNDETERMINED:
console.log("Gesture state: UNDETERMINED");
break;
case State.FAILED:
console.log("Gesture state: FAILED");
break;
case State.BEGAN:
console.log("Gesture state: BEGAN");
break;
case State.CANCELLED:
console.log("Gesture state: CANCELLED");
break;
case State.ACTIVE:
console.log("Gesture state: ACTIVE");
break;
case State.END:
console.log("Gesture state: END");
break;
}
}Events provide timing information for performance analysis:
function analyzeEventTiming(event: GestureUpdateEvent) {
// Most events include timestamp information
const timestamp = Date.now();
console.log(`Event processed at: ${timestamp}`);
// For long press gestures, duration is available
if ('duration' in event) {
console.log(`Long press duration: ${event.duration}ms`);
}
}Gesture update events fire frequently. Optimize handlers for performance:
import { runOnUI } from "react-native-reanimated";
// ✅ Good: Use runOnUI for performance-critical calculations
const panGesture = Gesture.Pan().onUpdate((event) => {
'worklet';
runOnUI(() => {
// Perform calculations on UI thread
const distance = Math.sqrt(event.translationX ** 2 + event.translationY ** 2);
console.log(`Distance: ${distance}`);
})();
});
// ❌ Avoid: Heavy calculations on JavaScript thread
const badPanGesture = Gesture.Pan().onUpdate((event) => {
// Heavy calculation on JS thread - will cause stuttering
const expensiveCalculation = performComplexMath(event);
});Properly clean up event handlers to prevent memory leaks:
import React, { useEffect, useCallback } from "react";
function MemoryEfficientEvents() {
const handleUpdate = useCallback((event) => {
// Event handling logic
}, []);
useEffect(() => {
// Cleanup if needed
return () => {
// Clean up resources
};
}, []);
const gesture = Gesture.Pan().onUpdate(handleUpdate);
return (
<GestureDetector gesture={gesture}>
{/* Component content */}
</GestureDetector>
);
}Install with Tessl CLI
npx tessl i tessl/npm-react-native-gesture-handler