公共手势类属性
笔者在第 2 节公共事件类属性中讲述组件的公共事件属性,比如点击事件、触摸事件等,这些事件默认遵循冒泡机制,ArkUI 开发框架提供了 3 种手势识别方法供开发者控制事件的冒泡机制,本节笔者简单介绍一下这三种手势识别器的用法。
手势类属性定义介绍
declare class CommonMethod<T> {
gesture(gesture: GestureType, mask?: GestureMask): T;
priorityGesture(gesture: GestureType, mask?: GestureMask): T;
parallelGesture(gesture: GestureType, mask?: GestureMask): T;
}
declare type GestureType = TapGestureInterface // 点击手势,支持单次点击、多次点击识别。
| LongPressGestureInterface // 长按手势。
| PanGestureInterface // 平移手势。
| PinchGestureInterface // 捏合手势。
| SwipeGestureInterface // 擦除手势。
| RotationGestureInterface // 旋转手势。
| GestureGroupInterface; // 手势识别组,多种手势组合为复合手势,支持连续识别、并行识别和互斥识别。
declare enum GestureMask {
Normal, // 不屏蔽子组件的手势,按照默认手势识别顺序进行识别。
IgnoreInternal, // 屏蔽子组件的手势,仅当前容器的手势进行识别。注意:子组件上系统内置的手势不会被屏蔽,如子组件为List组件时,内置的滑动手势仍然会触发。
}
CommonMethod
提供了 gesture()
、 priorityGesture()
和 parallelGesture()
3 个绑定手势识别器的方法, 它们区别如下:
gesture:给当前组件绑定手势识别器,子组件优于父组件识别手势。
priorityGesture:绑定优先识别手势。默认情况下,子组件优先于父组件识别手势,当父组件配置此方法时,父组件优先于子组件进行识别。
parallelGesture:绑定可与子组件手势同时触发的手势。手势事件为非冒泡事件。父组件设置此方法时,父子组件相同的手势事件都可以触发,实现类似冒泡效果。
以上 3 个方法的参数都是一致的,参数 gesture 表示手势识别器,
GestureType 提供了以下 7 种手势识别器
TapGesture:点击手势,支持单次点击、多次点击识别。
LongPressGesture:长按手势。
PanGesture:平移手势。
PinchGesture:捏合手势。
RotationGesture:旋转手势。
SwipeGesture:擦除手势。
GestureGroup:手势识别组,多种手势组合为复合手势,支持连续识别、并行识别和互斥识别。
手势动作 | 动作 |
---|---|
TapGesture | 点击手势,支持单次点击、多次点击识别 |
LongPressGesture | 长按手势 |
PanGesture | 平移手势 |
PinchGesture | 捏合手势 |
RotationGesture | 旋转手势 |
SwipeGesture | 擦除手势 |
GestureGroup | 手势识别组,多种手势组合为复合手势,支持连续识别、并行识别和互斥识别。 |
mask
表示设置父子组件对的手势识别顺序, GestureMask
提供了以下 2 种识别顺序:
Normal(默认值):不屏蔽子组件的手势,按照默认手势识别顺序进行识别。
IgnoreInternal:屏蔽子组件的手势,仅当前父组件的手势进行识别。注意:子组件上系统内置的手势不会被屏蔽,如子组件为 List 组件时,内置的滑动手势仍然会触发。
接下来笔者分别介绍一下以上各种手势识别器的用法
点击手势 TapGesture
interface TapGestureInterface {
(value?: { count?: number; fingers?: number }): TapGestureInterface;
onAction(event: (event?: GestureEvent) => void): TapGestureInterface;
}
创建点击手势识别器时可以配置相关参数, count 表示识别次数, fingers 表示手指数量, onAction 表示点击手势识别的事件回调。
gesture
:给当前组件绑定手势识别器,子组件优于父组件识别手势。
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbccaa")
.gesture( // 子组件设置手势识别
TapGesture({
count: 1,
fingers: 1
}).onAction((event) => {
this.info = "TapGesture in children";
console.log("TapGesture in children")
}
), GestureMask.Normal) // 子组件事件类型为Normal
.backgroundColor("#bbaacc")
}
.width("100%")
.height(120)
.id("parent")
.gesture( // 父组件设置手势识别
TapGesture({
count: 1,
fingers: 1
}).onAction((event) => {
this.info = "TapGesture in parent";
console.log("TapGesture in parent")
}
), GestureMask.IgnoreInternal) // 父组件事件类型为IgnoreInternal
.backgroundColor("#aabbcc")
}
.width('100%')
.height('100%')
.padding(10)
}
}
样例运行结果如下图所示:
如上所示, id
为 child
和 parent
的父子组件同时通过 gesture()
方法设置了手势识别器,事件按照正常派发流程派发给子组件。
笔者在测试 gesture()
方法时,无论父组件的识别顺序 GestureMask
设置成 Normal
还是 IgnoreInternal
,结果均不起作用。
priorityGesture
:绑定优先识别手势,父组件优先于子组件识别手势。
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbccaa")
.gesture( // 子组件设置手势识别
TapGesture({
count: 1,
fingers: 1
}).onAction((event) => {
this.info = this.info + " | TapGesture in children";
console.log("TapGesture in children")
}
), GestureMask.Normal) // 子组件事件类型为Normal
.backgroundColor("#bbaacc")
}
.width("100%")
.height(120)
.id("parent")
.priorityGesture( // 父组件设置手势识别
TapGesture({
count: 1,
fingers: 1
}).onAction((event) => {
this.info = "TapGesture in parent";
console.log("TapGesture in parent")
}
), GestureMask.IgnoreInternal) // 父组件事件类型为IgnoreInternal
.backgroundColor("#aabbcc")
}
.width('100%')
.height('100%')
.padding(10)
}
}
样例运行结果如下图所示:
如上所示, id
为 parent
的父组件通过 priorityGesture()
方法设置了手势识别器, id
为 child
的子组件通过 gesture()
方法设置了手势识别器,事件优先派发给了父组件而不会派发给子组件。
笔者在测试 gesture()
方法时,无论父组件的识别顺序 GestureMask
设置成 Normal
还是 IgnoreInternal
,结果均不起作用。
parallelGesture
:绑定可与子组件手势同时触发的手势。
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbccaa")
.gesture( // 子组件设置手势识别
TapGesture({
count: 1,
fingers: 1
}).onAction((event) => {
this.info = this.info + " | in children";
console.log("TapGesture in children")
}
), GestureMask.Normal) // 子组件事件类型为Normal
.backgroundColor("#bbaacc")
}
.width("100%")
.height(120)
.id("parent")
.parallelGesture( // 父组件设置手势识别
TapGesture({
count: 1,
fingers: 1
}).onAction((event) => {
this.info = "TapGesture in parent";
console.log("TapGesture in parent")
}
), GestureMask.IgnoreInternal) // 父组件事件类型为IgnoreInternal
.backgroundColor("#aabbcc")
}
.width('100%')
.height('100%')
.padding(10)
}
}
样例运行结果如下图所示:
如上所示, id
为 parent
的父组件通过 parallelGesture()
方法设置了手势识别器, id
为 child
的子组件通过 gesture()
方法设置了手势识别器,事件同时派发给了父组件和子组件。
笔者在测试 gesture()
方法时,无论父组件的识别顺序 GestureMask
设置成 Normal
还是 IgnoreInternal
,结果均不起作用
长按手势 LongPressGesture
- 语法
interface LongPressGestureInterface {
(value?: { fingers?: number; repeat?: boolean; duration?: number }): LongPressGestureInterface;
onAction(event: (event?: GestureEvent) => void): LongPressGestureInterface;
onActionEnd(event: (event?: GestureEvent) => void): LongPressGestureInterface;
onActionCancel(event: () => void): LongPressGestureInterface;
}
创建长按手势识别器时可以配置相关参数,
类型 | 说明 |
---|---|
fingers | 表示手指数量 |
repeat | 表示重复识别 |
duration | 表示长按时间 |
onAction | 表示长按手势识别的事件回调 |
onActionEnd | 表示长按结束时的回调 |
onActionCancel | 表示长按取消的回调 |
- gesture:给当前组件绑定手势识别器,子组件优于父组件识别手势。
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbaacc")
.gesture( // 子组件设置手势识别
LongPressGesture({
duration: 800, // 长按800毫秒
repeat: false, // 不重复识别
fingers: 1 // 单个手指
})
.onAction(() => {
this.info = this.info + " | child:action";
})
.onActionEnd(() => {
this.info = this.info + ", end";
})
.onActionCancel(() => {
this.info = this.info + ", cancel";
})
)
}
.width("100%")
.height(120)
.id("parent")
.backgroundColor("#aabbcc")
.gesture( // 子组件设置手势识别
LongPressGesture({
duration: 800, // 长按800毫秒
repeat: false, // 不重复识别
fingers: 1 // 单个手指
})
.onAction(() => {
this.info = "parent:action";
})
.onActionEnd(() => {
this.info = this.info + ", end";
})
.onActionCancel(() => {
this.info = this.info + ", cancel";
}),
GestureMask.IgnoreInternal)
}
.width('100%')
.height('100%')
.padding(10)
}
}
样例运行结果如下图所示:
如上所示, id
为 child
和 parent
的父子组件同时通过 gesture()
方法设置了手势识别器,事件按照正常派发流程派发给子组件。
笔者在测试 gesture()
方法时,无论父组件的识别顺序 GestureMask
设置成 Normal
还是 IgnoreInternal
,结果均不起作用。
- priorityGesture:绑定优先识别手势,父组件优先于子组件识别手势。
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbaacc")
.gesture( // 子组件设置手势识别
LongPressGesture({
duration: 800, // 长按800毫秒
repeat: false, // 不重复识别
fingers: 1 // 单个手指
})
.onAction(() => {
this.info = this.info + " | child:action";
})
.onActionEnd(() => {
this.info = this.info + ", end";
})
.onActionCancel(() => {
this.info = this.info + ", cancel";
})
)
}
.width("100%")
.height(120)
.id("parent")
.backgroundColor("#aabbcc")
.priorityGesture( // 父组件设置手势识别
LongPressGesture({
duration: 800, // 长按800毫秒
repeat: false, // 不重复识别
fingers: 1 // 单个手指
})
.onAction(() => {
this.info = "parent:action";
})
.onActionEnd(() => {
this.info = this.info + ", end";
})
.onActionCancel(() => {
this.info = this.info + ", cancel";
}),
GestureMask.IgnoreInternal)
}
.width('100%')
.height('100%')
.padding(10)
}
}
样例运行结果如下图所示:
如上所示, id
为 parent
的父组件通过 priorityGesture()
方法设置了手势识别器, id
为 child
的子组件通过 gesture()
方法设置了手势识别器,事件优先派发给了父组件而不会派发给子组件
笔者在测试 gesture() 方法时,无论父组件的识别顺序 GestureMask 设置成 Normal 还是 IgnoreInternal ,结果均不起作用。
parallelGesture
:绑定可与子组件手势同时触发的手势。
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbaacc")
.gesture( // 子组件设置手势识别
LongPressGesture({
duration: 800, // 长按800毫秒
repeat: false, // 不重复识别
fingers: 1 // 单个手指
})
.onAction(() => {
this.info = this.info + " | c:action";
})
.onActionEnd(() => {
this.info = this.info + ", cend";
})
.onActionCancel(() => {
this.info = this.info + ", ccancel";
})
)
}
.width("100%")
.height(120)
.id("parent")
.backgroundColor("#aabbcc")
.parallelGesture( // 父组件设置手势识别
LongPressGesture({
duration: 800, // 长按800毫秒
repeat: false, // 不重复识别
fingers: 1 // 单个手指
})
.onAction(() => {
this.info = "p:action";
})
.onActionEnd(() => {
this.info = this.info + ", pend";
})
.onActionCancel(() => {
this.info = this.info + ", pcancel";
}),
GestureMask.IgnoreInternal
)
}
.width('100%')
.height('100%')
.padding(10)
}
}
样例运行结果如下图所示:
如上所示, id
为 parent
的父组件通过 parallelGesture()
方法设置了手势识别器, id
为 child
的子组件通过 gesture()
方法设置了手势识别器,事件同时派发给了父组件和子组件。
笔者在测试 gesture()
方法时,无论父组件的识别顺序 GestureMask
设置成 Normal
还是 IgnoreInternal
,结果均不起作用。
平移手势 PanGesture
interface PanGestureInterface {
(value?: { fingers?: number; direction?: PanDirection; distance?: number } | PanGestureOptions): PanGestureInterface;
onActionStart(event: (event?: GestureEvent) => void): PanGestureInterface;
onActionUpdate(event: (event?: GestureEvent) => void): PanGestureInterface;
onActionEnd(event: (event?: GestureEvent) => void): PanGestureInterface;
onActionCancel(event: () => void): PanGestureInterface;
}
创建平移手势识别器时可以配置相关参数, fingers 表示手指数量, direction 表示平移方向, distance 表示平移距离, onActionXXX 表示平移时的事件回调。
参数 | 说明 |
---|---|
fingers | 表示手指数量 |
direction | 表示平移方向 |
distance | 表示平移距离 |
onActionXXXX | 表示平移时的事件回调 |
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbaacc")
.gesture( // 子组件设置手势识别
PanGesture({
fingers: 1, // 单个手指
direction: PanDirection.Horizontal, // 水平方向移动
distance: 20 // 平移距离
})
.onActionStart(() => {
this.info = this.info + " | cs";
})
.onActionUpdate(() => {
this.info = this.info + ", cu";
})
.onActionEnd(() => {
this.info = this.info + ", ce";
})
.onActionCancel(() => {
this.info = this.info + ", cc";
})
)
}
.width("100%")
.height(120)
.id("parent")
.backgroundColor("#aabbcc")
.gesture( // 父组件设置手势识别
PanGesture({
fingers: 1, // 单个手指
direction: PanDirection.Horizontal, // 水平方向移动
distance: 20 // 平移距离
})
.onActionStart(() => {
this.info = this.info + " | cs";
})
.onActionUpdate(() => {
this.info = this.info + ", cu";
})
.onActionEnd(() => {
this.info = this.info + ", ce";
})
.onActionCancel(() => {
this.info = this.info + ", cc";
}),
GestureMask.IgnoreInternal
)
}
.width('100%')
.height('100%')
.padding(10)
}
}
捏合手势 PinchGesture
interface PinchGestureInterface {
(value?: { fingers?: number; distance?: number }): PinchGestureInterface;
onActionStart(event: (event?: GestureEvent) => void): PinchGestureInterface;
onActionUpdate(event: (event?: GestureEvent) => void): PinchGestureInterface;
onActionEnd(event: (event?: GestureEvent) => void): PinchGestureInterface;
onActionCancel(event: () => void): PinchGestureInterface;
}
创建平移手势识别器时可以配置相关参数, fingers 表示手指数量, direction 表示平移方向, distance 表示平移距离, onActionXXX 表示平移时的事件回调。
参数 | 说明 |
---|---|
fingers | 表示手指数量 |
distance | 表示平移距离 |
onActionXXXX | 表示平移时的事件回调 |
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbaacc")
.gesture( // 子组件设置手势识别
PinchGesture({
fingers: 1, // 2个手指
distance: 20 // 捏合距离
})
.onActionStart(() => {
this.info = this.info + " | cs";
})
.onActionUpdate(() => {
this.info = this.info + ", cu";
})
.onActionEnd(() => {
this.info = this.info + ", ce";
})
.onActionCancel(() => {
this.info = this.info + ", cc";
})
)
}
.width("100%")
.height(120)
.id("parent")
.backgroundColor("#aabbcc")
}
.width('100%')
.height('100%')
.padding(10)
}
}
旋转手势 RotationGesture
interface RotationGestureInterface {
(value?: { fingers?: number; angle?: number }): RotationGestureInterface;
onActionStart(event: (event?: GestureEvent) => void): RotationGestureInterface;
onActionUpdate(event: (event?: GestureEvent) => void): RotationGestureInterface;
onActionEnd(event: (event?: GestureEvent) => void): RotationGestureInterface;
onActionCancel(event: () => void): RotationGestureInterface;
}
创建旋转手势识别器时可以配置相关参数, fingers
表示手指数量, angle
表示旋转角度, onActionXXX
表示平移时的事件回调。
@Entry @Component struct GestureTest {
@State info: string = "Gesture...";
build() {
Column({space: 10}) {
Text(this.info)
.width("100%")
.fontSize(22)
.textAlign(TextAlign.Center)
Stack() {
Text("")
.width(200)
.height(100)
.fontSize(20)
.id("child")
.backgroundColor("#bbaacc")
.gesture( // 子组件设置手势识别
RotationGesture({
fingers: 2, // 2个手指
angle: 20 // 旋转角度
})
.onActionStart(() => {
this.info = this.info + " | cs";
})
.onActionUpdate(() => {
this.info = this.info + ", cu";
})
.onActionEnd(() => {
this.info = this.info + ", ce";
})
.onActionCancel(() => {
this.info = this.info + ", cc";
})
)
}
.width("100%")
.height(120)
.id("parent")
.backgroundColor("#aabbcc")
}
.width('100%')
.height('100%')
.padding(10)
}
}