多层级手势事件指父子组件嵌套时,父子组件均绑定了手势或事件。在该场景下,手势或者事件的响应受到多个因素的影响,相互之间发生传递和竞争,容易出现预期外的响应。对于多层级手势使用一般有下面几种问题场景:
常见问题场景 | 问题简述 |
|---|---|
场景一 | Stack组件设置并行手势导致手势冲突 |
场景二 | 如何阻止onTouch事件从子组件传向父组件 |
场景三 | 如何隔离两个自定义控件的触摸事件 |
场景四 | 手势如何从上层组件向下层组件透传 |
Stack组件绑定并行手势,触发Stack长按手势情况下,如何使Stack内子组件点击事件不触发?
问题代码如下:
@Entry
@Component
struct StackExample {
@State count: number = 0;
build() {
Stack({ alignContent: Alignment.Bottom }) {
Text('First child, show in bottom')
.width('90%')
.height('100%')
.backgroundColor('#f1f3f5')
.textAlign(TextAlign.Center)
.borderRadius(10)
.gesture(
LongPressGesture()
.onAction(() => {
console.info('text 点击');
})
);
}.width('100%').height(150).margin({ top: 5 })
.parallelGesture(
LongPressGesture()
.onAction(() => {
console.info('stack 长按');
}), GestureMask.Normal);
}
} 由于父组件设置parallelGesture时,父子组件相同的手势事件都可以触发,导致长按Stack会触发子组件点击事件,可以通过给子组件加上长按事件和组件的点击事件做竞争。
示例代码如下:
@Entry
@Component
struct StackExample {
build() {
Stack({ alignContent: Alignment.Bottom }) {
Text('First child, show in bottom')
.width('90%')
.height('100%')
.backgroundColor('#f1f3f5')
.textAlign(TextAlign.Center)
.borderRadius(10)
.gesture(
GestureGroup(GestureMode.Exclusive,
LongPressGesture()
.onAction(() => {
console.info('Text 长按');
}),
TapGesture()
.onAction(() => {
console.info('Text 点击');
})
)
);
}.width('100%').height(150).margin({ top: 5 })
.parallelGesture(
LongPressGesture()
.onAction(() => {
console.info('stack 长按');
}), GestureMask.Normal);
}
} 效果如图:

在子组件onTouch事件回调中调用stopPropagation阻断触摸事件向父组件传递。
子组件调用stopPropagation只会阻止父组件响应onTouch事件,无法阻止onClick事件的触发。
示例代码如下
@Entry
@Component
struct TouchExample {
text: string = '';
build() {
Column() {
Button('Touch')
.height(40)
.width(100)
.onTouch((event?: TouchEvent) => {
console.info('child onTouch');
event?.stopPropagation();
});
Text(this.text);
}
.onTouch(() => {
console.info('father onTouch');
})
.onClick(() => {
console.info('father onClick');
})
.width('100%')
.padding(30);
}
} 效果如图:

ArkUI事件响应链通过触摸测试进行收集,遵循右子树(按组件布局的先后层级)优先的后序遍历。
hitTestBehavior属性均为默认,自身及子节点响应触摸测试,但阻塞兄弟节点的触摸测试,不影响祖先节点的触摸测试。
如果想实现手势事件从组件上层传递下层,可设置hitTestBehavior为HitTestMode.Transparent,自身和子节点均响应触摸测试,不会阻塞兄弟节点和祖先节点的触摸测试,具体使用可参考示例:hitTestBehavior对手势和事件的控制。