Gestures
The Scripting app provides a gesture system similar to SwiftUI, allowing any view (<VStack>, <HStack>, <Text>, etc.) to respond to touch interactions such as tapping, long pressing, dragging, rotating, and magnifying.
You can use:
- Simplified gesture properties like
onTapGesture, onLongPressGesture, onDragGesture, or
- Advanced gesture objects such as
TapGesture(), LongPressGesture(), and the gesture modifiers for composition and priority control.
1. Simple Gesture Properties
These are convenient, shorthand ways to add gestures directly to a view.
onTapGesture
Executes an action when a tap gesture is recognized.
Type
onTapGesture?: (() => void) | {
count: number
perform: () => void
}
Parameters
Examples
// Single tap
<VStack onTapGesture={() => console.log('Tapped')} />
// Double tap
<HStack
onTapGesture={{
count: 2,
perform: () => console.log('Double tapped')
}}
/>
onLongPressGesture
Executes an action when a long press gesture is recognized.
Type
onLongPressGesture?: (() => void) | {
minDuration?: number
maxDuration?: number
perform: () => void
onPressingChanged?: (state: boolean) => void
}
Parameters
Examples
// Simple usage
<VStack onLongPressGesture={() => console.log('Long pressed')} />
// Custom duration and press state callback
<HStack
onLongPressGesture={{
minDuration: 800,
maxDuration: 3000,
perform: () => console.log('Long press success'),
onPressingChanged: isPressing =>
console.log(isPressing ? 'Pressing...' : 'Released')
}}
/>
onDragGesture
Adds a drag gesture to a view, tracking position, offset, and velocity.
Type
onDragGesture?: {
minDistance?: number
coordinateSpace?: 'local' | 'global'
onChanged?: (details: DragGestureDetails) => void
onEnded?: (details: DragGestureDetails) => void
}
Parameters
DragGestureDetails
type DragGestureDetails = {
time: number
location: Point
startLocation: Point
translation: Size
velocity: Size
predictedEndLocation: Point
predictedEndTranslation: Size
}
Example
<VStack
onDragGesture={{
minDistance: 5,
coordinateSpace: 'global',
onChanged: details => {
console.log('Location:', details.location)
console.log('Offset:', details.translation)
},
onEnded: details => {
console.log('Predicted end:', details.predictedEndLocation)
}
}}
/>
2. Gesture Classes (Advanced Usage)
For complex interaction handling or gesture composition, use the gesture constructors and modifiers.
GestureInfo Class
All gesture constructors return a GestureInfo object that defines configuration and callbacks.
class GestureInfo<Options, Value> {
type: string
options: Options
onChanged(callback: (value: Value) => void): this
onEnded(callback: (value: Value) => void): this
}
Example
<Text
gesture={
TapGesture()
.onEnded(() => console.log('Tapped'))
}
/>
TapGesture
Detects single or multiple taps.
declare function TapGesture(count?: number): GestureInfo<number | undefined, void>
Example
<Text
gesture={
TapGesture(2)
.onEnded(() => console.log('Double tapped'))
}
/>
LongPressGesture
Detects press and hold gestures.
declare function LongPressGesture(options?: LongPressGestureOptions): GestureInfo<LongPressGestureOptions, boolean>
type LongPressGestureOptions = {
minDuration?: number
maxDuration?: number
}
Example
<Text
gesture={
LongPressGesture({ minDuration: 800 })
.onChanged(() => console.log('Pressing...'))
.onEnded(() => console.log('Long press finished'))
}
/>
DragGesture
Tracks finger or pointer movement.
declare function DragGesture(options?: DragGestureOptions): GestureInfo<DragGestureOptions, DragGestureDetails>
type DragGestureOptions = {
minDistance?: number
coordinateSpace?: 'local' | 'global'
}
Example
<VStack
gesture={
DragGesture({ coordinateSpace: 'global' })
.onChanged(d => console.log('Offset', d.translation))
.onEnded(d => console.log('Velocity', d.velocity))
}
/>
MagnifyGesture
Detects pinch zoom gestures.
declare function MagnifyGesture(minScaleDelta?: number | null): GestureInfo<number | null | undefined, MagnifyGestureValue>
type MagnifyGestureValue = {
time: Date
magnification: number
startAnchor: Point
startLocation: Point
velocity: number
}
Example
<Text
gesture={
MagnifyGesture(0.05)
.onChanged(v => console.log('Scale', v.magnification))
.onEnded(() => console.log('Zoom ended'))
}
/>
RotateGesture
Detects rotation gestures.
declare function RotateGesture(minAngleDelta?: Angle | null): GestureInfo<Angle | null | undefined, RotateGestureValue>
type RotateGestureValue = {
rotation: AngleValue
velocity: AngleValue
startAnchor: Point
time: Date
}
type AngleValue = {
radians: number
degrees: number
magnitude: number
animatableData: number
}
Example
<ZStack
gesture={
RotateGesture()
.onChanged(v => console.log('Rotation', v.rotation.degrees))
.onEnded(() => console.log('Rotation ended'))
}
/>
3. Gesture Modifiers for Views
All views support the following gesture-related properties.
type GesturesProps = {
gesture?: GestureProps
simultaneousGesture?: GestureProps
highPriorityGesture?: GestureProps
defersSystemGestures?: EdgeSet
}
gesture
Adds a gesture to the view.
<Text
gesture={
TapGesture()
.onEnded(() => console.log('Tapped'))
}
/>
highPriorityGesture
Adds a gesture with higher priority than existing ones on the view.
<Text
highPriorityGesture={
TapGesture(2)
.onEnded(() => console.log('Double tap takes priority'))
}
/>
simultaneousGesture
Allows multiple gestures to be recognized simultaneously.
<Text
simultaneousGesture={
LongPressGesture()
.onEnded(() => console.log('Long pressed'))
}
gesture={
TapGesture()
.onEnded(() => console.log('Tapped'))
}
/>
Gives your custom gestures precedence over system gestures originating from screen edges.
<VStack defersSystemGestures="all">
<Text>Custom gestures take precedence</Text>
</VStack>
Accepted Values
4. GestureMask
Controls how adding a gesture affects other gestures on the same view or its subviews.
type GestureMask = "all" | "gesture" | "subviews" | "none"
Example
<VStack
gesture={{
gesture: TapGesture().onEnded(() => console.log('Tapped')),
mask: 'gesture'
}}
>
<Text>Tap here</Text>
</VStack>
5. Summary Table