如何解决多层级组件手势冲突
=============

#### 问题现象

多层级手势事件指父子组件嵌套时，父子组件均绑定了手势或事件。在该场景下，手势或者事件的响应受到多个因素的影响，相互之间发生传递和竞争，容易出现预期外的响应。对于多层级手势使用一般有下面几种问题场景：

| 
常见问题场景

 | 

问题简述

 |
| :-- | :-- |
| 

场景一

 | 

Stack组件设置并行手势导致手势冲突

 |
| 

场景二

 | 

如何阻止onTouch事件从子组件传向父组件

 |
| 

场景三

 | 

如何隔离两个自定义控件的触摸事件

 |
| 

场景四

 | 

手势如何从上层组件向下层组件透传

 |

#### \[h2\]场景一

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);
  }
}

#### \[h2\]场景二

PanGesture绑定在父组件上，子组件有绑定onTouch，如何在子组件onTouch的时候，阻止父组件响应PanGesture？

#### \[h2\]场景三

如何隔离两个自定义控件的触摸事件？

#### \[h2\]场景四

界面覆盖一个透明度为0的Stack组件后，下层组件不再响应手势事件？如何实现下层组件手势响应？

#### 背景知识

*   [parallelGesture](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-gesture-settings#parallelgesture)：绑定可与子组件手势同时触发的手势。手势事件为非冒泡事件。父组件设置parallelGesture时，父子组件相同的手势事件都可以触发，实现类似冒泡效果。
*   [事件冒泡](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-interaction-basic-principles#事件冒泡)：基础事件在响应链上的传递遵循冒泡机制，即最内层组件优先处理，再逐层往父组件传递该事件，任意一层组件可主动终止本次事件的继续传递，即终止冒泡。但需要注意的是，终止冒泡并不会中断父组件对手势的响应处理。
*   [组合手势](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-combined-gestures)：手势识别组合，即两种及以上手势组合为复合手势，支持顺序识别、并发识别和互斥识别。
*   [事件独占控制](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-monopolize-events)：在一个窗口内，设置了独占控制的组件上的事件如果首先响应，则本次交互只允许此组件上设置的事件响应，窗口内其他组件上的事件不会响应。
*   [hitTestBehavior](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-hit-test-behavior#hittestbehavior)：可以实现在复杂的多层级场景下，一些组件能够响应手势和事件，而一些组件不能响应手势和事件。

#### 解决方案

#### \[h2\]场景一

由于父组件设置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);
  }
}

效果如图：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/75/v3/-Y-ffUCTSguUwLSd2YMY4w/zh-cn_image_0000002658792003.png?HW-CC-KV=V1&HW-CC-Date=20260709T133908Z&HW-CC-Expire=86400&HW-CC-Sign=7CC1B786770CC3139F7E063A2AB14FB0AFF8F2A610F08671AFB4B9509895CAAC "点击放大")

#### \[h2\]场景二

在子组件onTouch事件回调中调用stopPropagation阻断触摸事件向父组件传递。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/1b/v3/wKVYENh1RvyQXW62ETkwWw/caution_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T133908Z&HW-CC-Expire=86400&HW-CC-Sign=BCAF894228102E9567DDF15B9D972D7864CF83784B7BB61F006B7CDC2F67CD0A)

子组件调用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);
  }
}

效果如图：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/10/v3/mi9o8myiRQCe4BVhH8l8Kg/zh-cn_image_0000002628552626.png?HW-CC-KV=V1&HW-CC-Date=20260709T133908Z&HW-CC-Expire=86400&HW-CC-Sign=F4B8CD62DDD1FD999BADB84B2C8B3ED4929B0A0770879FB822541BB9F0ED40F2 "点击放大")

#### \[h2\]场景三

通过配置monopolizeEvents是否独占事件实现隔离两个自定义控件的触摸事件，true表示组件独占事件，false表示组件不独占事件，具体使用示例可参考[示例](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-monopolize-events#示例)。

#### \[h2\]场景四

ArkUI事件响应链通过触摸测试进行收集，遵循右子树（按组件布局的先后层级）优先的后序遍历。

hitTestBehavior属性均为默认，自身及子节点响应触摸测试，但阻塞兄弟节点的触摸测试，不影响祖先节点的触摸测试。

如果想实现手势事件从组件上层传递下层，可设置hitTestBehavior为HitTestMode.Transparent，自身和子节点均响应触摸测试，不会阻塞兄弟节点和祖先节点的触摸测试，具体使用可参考示例：[hitTestBehavior对手势和事件的控制](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-gesture-events-multi-level-gesture#hittestbehavior对手势和事件的控制)。