手势

Scripting 提供了与 SwiftUI 类似的完整手势系统,可为任意视图(如 <VStack><HStack><Text> 等)添加点击、长按、拖动、缩放、旋转等交互行为。 开发者既可以使用简化的 onTapGesture / onLongPressGesture / onDragGesture 等直接属性,也可以使用新的 Gesture 类接口和 gesture 修饰符,以获得更灵活的组合方式。


一、直接手势属性(简化用法)

这些属性提供最直接的交互绑定方式,适合快速使用场景。


1. onTapGesture

在识别到点击手势时执行指定操作。

类型

1onTapGesture?: (() => void) | {
2  count: number
3  perform: () => void
4}

参数

参数 类型 默认值 说明
count number 1 点击次数(1 为单击,2 为双击)
perform () => void 识别到点击后执行的操作

示例

1// 单击触发
2<VStack onTapGesture={() => console.log('点击了')} />
3
4// 双击触发
5<HStack
6  onTapGesture={{
7    count: 2,
8    perform: () => console.log('双击了')
9  }}
10/>

2. onLongPressGesture

在识别到长按手势时执行操作,可监听按压状态。

类型

1onLongPressGesture?: (() => void) | {
2  minDuration?: number
3  maxDuration?: number
4  perform: () => void
5  onPressingChanged?: (state: boolean) => void
6}

参数

参数 类型 默认值 说明
minDuration number 500 触发长按所需最短时间(毫秒)
maxDuration number 10000 长按的最长持续时间(毫秒)
perform () => void 长按触发时执行的操作
onPressingChanged (state: boolean) => void 按下或松开时的状态回调

示例

1// 基本用法
2<VStack onLongPressGesture={() => console.log('长按触发')} />
3
4// 自定义参数
5<HStack
6  onLongPressGesture={{
7    minDuration: 800,
8    maxDuration: 3000,
9    perform: () => console.log('长按成功'),
10    onPressingChanged: isPressing =>
11      console.log(isPressing ? '正在按压' : '已松开')
12  }}
13/>

3. onDragGesture

为视图添加拖动交互,支持实时位置变化与拖动结束事件。

类型

1onDragGesture?: {
2  minDistance?: number
3  coordinateSpace?: 'local' | 'global'
4  onChanged?: (details: DragGestureDetails) => void
5  onEnded?: (details: DragGestureDetails) => void
6}

参数

参数 类型 默认值 说明
minDistance number 10 触发拖动的最小距离(点)
coordinateSpace 'local' | 'global' 'local' 坐标系类型
onChanged (details: DragGestureDetails) => void 拖动过程中回调
onEnded (details: DragGestureDetails) => void 拖动结束时回调

DragGestureDetails 类型

1type DragGestureDetails = {
2  time: number
3  location: Point
4  startLocation: Point
5  translation: Size
6  velocity: Size
7  predictedEndLocation: Point
8  predictedEndTranslation: Size
9}
字段 说明
time 当前事件时间戳(毫秒)
location 当前触摸位置 {x, y}
startLocation 拖动起始位置
translation 从开始拖动至当前的偏移量
velocity 当前速度(points/second)
predictedEndLocation 预测结束位置
predictedEndTranslation 预测总偏移量

示例

1<VStack
2  onDragGesture={{
3    minDistance: 5,
4    coordinateSpace: 'global',
5    onChanged: details => {
6      console.log('当前坐标:', details.location)
7      console.log('偏移量:', details.translation)
8    },
9    onEnded: details => {
10      console.log('预测结束位置:', details.predictedEndLocation)
11    }
12  }}
13/>

二、Gesture 类接口(高级用法)

若需要更复杂的组合或同时识别多个手势,可使用 Gesture 类与 gesture 修饰符。

所有手势均返回一个 GestureInfo 实例,通过 .onChanged().onEnded() 注册事件。


1. GestureInfo 类

1class GestureInfo<Options, Value> {
2  type: string
3  options: Options
4  onChanged(callback: (value: Value) => void): this
5  onEnded(callback: (value: Value) => void): this
6}
方法 说明
.onChanged(callback) 手势状态变化时调用(如拖动中、缩放中)
.onEnded(callback) 手势结束时调用

示例

1<Text
2  gesture={
3    TapGesture()
4      .onEnded(() => console.log('点击结束'))
5  }
6/>

2. TapGesture(点击手势)

1declare function TapGesture(count?: number): GestureInfo<number | undefined, void>
参数 类型 默认值 说明
count number 1 点击次数

示例

1<Text
2  gesture={
3    TapGesture(2)
4      .onEnded(() => console.log('双击了'))
5  }
6/>

3. LongPressGesture(长按手势)

1declare function LongPressGesture(options?: LongPressGestureOptions): GestureInfo<LongPressGestureOptions, boolean>
2
3type LongPressGestureOptions = {
4  minDuration?: number
5  maxDuration?: number
6}
参数 默认值 说明
minDuration 500 触发所需的最短时间(毫秒)
maxDuration 10000 手指移动前的最长持续时间(毫秒)

示例

1<Text
2  gesture={
3    LongPressGesture({ minDuration: 800 })
4      .onChanged(() => console.log('正在长按'))
5      .onEnded(() => console.log('长按完成'))
6  }
7/>

4. DragGesture(拖动手势)

1declare function DragGesture(options?: DragGestureOptions): GestureInfo<DragGestureOptions, DragGestureDetails>
2
3type DragGestureOptions = {
4  minDistance?: number
5  coordinateSpace?: 'local' | 'global'
6}

示例

1<VStack
2  gesture={
3    DragGesture({ coordinateSpace: 'global' })
4      .onChanged(d => console.log('偏移', d.translation))
5      .onEnded(d => console.log('速度', d.velocity))
6  }
7/>

5. MagnifyGesture(缩放手势)

1declare function MagnifyGesture(minScaleDelta?: number | null): GestureInfo<number | null | undefined, MagnifyGestureValue>
2
3type MagnifyGestureValue = {
4  time: Date
5  magnification: number
6  startAnchor: Point
7  startLocation: Point
8  velocity: number
9}

示例

1<Text
2  gesture={
3    MagnifyGesture(0.05)
4      .onChanged(v => console.log('缩放倍率', v.magnification))
5      .onEnded(() => console.log('缩放结束'))
6  }
7/>

6. RotateGesture(旋转手势)

1declare function RotateGesture(minAngleDelta?: Angle | null): GestureInfo<Angle | null | undefined, RotateGestureValue>
2
3type RotateGestureValue = {
4  rotation: AngleValue
5  velocity: AngleValue
6  startAnchor: Point
7  time: Date
8}
9
10type AngleValue = {
11  radians: number
12  degrees: number
13  magnitude: number
14  animatableData: number
15}

示例

1<ZStack
2  gesture={
3    RotateGesture()
4      .onChanged(v => console.log('旋转角度', v.rotation.degrees))
5      .onEnded(() => console.log('旋转完成'))
6  }
7/>

三、手势修饰符(Gesture Modifiers)

以下属性可添加在任何视图上,用于控制手势识别行为。

1type GesturesProps = {
2  gesture?: GestureProps
3  simultaneousGesture?: GestureProps
4  highPriorityGesture?: GestureProps
5  defersSystemGestures?: EdgeSet
6}

1. gesture

为视图添加一个手势。

1<Text
2  gesture={
3    TapGesture()
4      .onEnded(() => console.log('点击'))
5  }
6/>

2. highPriorityGesture

使该手势的识别优先于同视图上的其他手势。

1<Text
2  highPriorityGesture={
3    TapGesture(2)
4      .onEnded(() => console.log('双击优先'))
5  }
6/>

3. simultaneousGesture

允许多个手势同时识别。

1<Text
2  simultaneousGesture={
3    LongPressGesture()
4      .onEnded(() => console.log('长按'))
5  }
6  gesture={
7    TapGesture()
8      .onEnded(() => console.log('点击'))
9  }
10/>

4. defersSystemGestures

设置屏幕边缘的优先权,使自定义手势优先于系统手势(如返回手势)。

1<VStack defersSystemGestures="all">
2  <Text>边缘手势优先</Text>
3</VStack>
说明
'top' 顶部边缘
'leading' 左边缘(RTL 时为右)
'trailing' 右边缘
'bottom' 底部边缘
'horizontal' 左右两侧
'vertical' 上下两侧
'all' 所有边缘

四、GestureMask(手势优先级控制)

定义当添加多个手势时的优先策略。

1type GestureMask = "all" | "gesture" | "subviews" | "none"
说明
"all" 启用所有手势(默认)
"gesture" 仅启用当前手势,禁用子视图手势
"subviews" 启用子视图手势,禁用当前手势
"none" 禁用所有手势

示例

1<VStack
2  gesture={{
3    gesture: TapGesture().onEnded(() => console.log('Tapped')),
4    mask: 'gesture'
5  }}
6>
7  <Text>Tap me</Text>
8</VStack>

五、总结对比表

手势类型 描述 对应类函数 直接属性 常用回调
点击 检测单击或多击 TapGesture onTapGesture .onEnded()
长按 检测持续按压 LongPressGesture onLongPressGesture .onChanged() / .onEnded()
拖动 检测移动轨迹 DragGesture onDragGesture .onChanged() / .onEnded()
缩放 双指缩放 MagnifyGesture .onChanged() / .onEnded()
旋转 双指旋转 RotateGesture .onChanged() / .onEnded()