手势
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/>
设置屏幕边缘的优先权,使自定义手势优先于系统手势(如返回手势)。
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() |