OpenHarmony开发者论坛

标题: OpenHarmony应用组件自定义事件分发 [打印本页]

作者: 深开鸿_张守忠    时间: 2024-1-16 19:57
标题: OpenHarmony应用组件自定义事件分发
[md]### 简介:

** ArkUI在处理触屏事件时,会在触屏事件触发前进行按压点和组件区域的触摸测试,来收集需要响应触屏事件的组件,再基于触摸测试结果分发相应的触屏事件。在父节点,可以通过onChildTouchTest决定如何让子节点去做触摸测试,影响子组件的触摸测试,最终影响后续的触屏事件分发 。**

### 文档环境:

* **开发环境:Windows 10专业版**
* **DevEco Studio版本:DevEco Studio 4.0Release (4.0.0.600)**
* **SDK版本:4.1.6.1 (full sdk)**
* **API版本:Version 11**
* **开发板型号:DAYU200(RK3568)**
* **系统版本:OpenHarmony 4.1.6.1**

### 演示demo:

* **新建一个 Stage 框架的 demo 工程,在page/Index.ets中通过stack组件封装大小两个圆形按钮组件,分别用蓝色和黄色的背景色来区分并分别增加OnClick事件,在事件回调函数中调用提示组件,提示OnClick事件已响应。**
* **在stack组件中增加onChildTouchTest属性,在其回调函数中通过 对参数TouchTestInfo进行解析,判断按压点是否在大圆小圆内或者在大圆外,如果在小圆内则向小圆分发事件,如果在大圆内但在小圆外则向小圆分发事件,其他情况不向大圆和小圆分发事件。**

** demo运行效果:**

| **首页**                                                                                                                                                                                                                              | **点击蓝圈**                                                                                                                                                                                                                             | **点击黄圈**                                                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ![image](file://D:/project/OpenHarmony_sample/sample_%E9%9C%80%E6%B1%82&%E8%AF%A6%E7%BB%86%E8%AE%BE%E8%AE%A1/custom_event/%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6%E5%88%86%E5%8F%91/screenshots/customClick.jpeg?lastModify=1705406242) | ![image](file://D:/project/OpenHarmony_sample/sample_%E9%9C%80%E6%B1%82&%E8%AF%A6%E7%BB%86%E8%AE%BE%E8%AE%A1/custom_event/%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6%E5%88%86%E5%8F%91/screenshots/customClickBig.jpeg?lastModify=1705406242) | ![image](file://D:/project/OpenHarmony_sample/sample_%E9%9C%80%E6%B1%82&%E8%AF%A6%E7%BB%86%E8%AE%BE%E8%AE%A1/custom_event/%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6%E5%88%86%E5%8F%91/screenshots/customClickSmall.jpeg?lastModify=1705406242) |

** 核心代码如下:**

```
import ShowToast from 'ShowToast';
import Logger from 'util/Logger';

const TAG: string = 'CustomClickEvent';

@Entry
@Component
struct CustomClickEvent {
 private btnFontColor: Resource = $r('app.color.white');

 isTouchPointInCircle(info: TouchTestInfo): boolean {
   let circleCenterX = info.rect.x + info.rect.width / 2;
   let circleCenterY = info.rect.y + info.rect.height / 2;
   let circleRadius = info.rect.width / 2;
   let distance = Math.sqrt((circleCenterX - info.parentX)**2 + (circleCenterY - info.parentY)**2);
   Logger.info(TAG, `TouchPoinInCircle circleCenterX: ${circleCenterX}, circleCenterY: ${circleCenterY},\
    circleRadius: ${circleRadius}, distance: ${distance}`);
   if (distance <= circleRadius) {
     return true;
   }
   return false;
  }

 build() {
   Column() {
     Column() {
       Column({ space: 12 }) {
         Stack({ alignContent: Alignment.Bottom }) {
           Button({ type: ButtonType.Circle }) {
             Row() {
               Text($r('app.string.custom_click_big_btn'))
                 .fontSize(21)
                 .fontWeight(500)
                 .fontFamily('HarmonyHeiTi-Medium')
                 .textAlign(TextAlign.Center)
                 .id('BigCircle')
                 .padding({ top: 56, bottom: 300 })
             }
             .alignItems(VerticalAlign.Top)
           }
           .backgroundColor('#007DFF')
           .width('100%')
           .height('100%')
           .fontSize(21)
           .fontWeight(500)
           .fontColor(this.btnFontColor)
           .onClick(() => {
             ShowToast.longToast($r('app.string.custom_bigcircle_prompt'));
           })

           Button($r('app.string.custom_click_small_btn'), { type: ButtonType.Circle })
             .backgroundColor('#F7CE00')
             .width(240)
             .fontSize(21)
             .fontWeight(500)
             .borderRadius(20)
             .fontColor(this.btnFontColor)
             .id('SmallCircle')
             .onClick(() => {
               ShowToast.longToast($r('app.string.custom_smallcircle_prompt'));
             })
         }
         .width('100%')
         .hitTestBehavior(HitTestMode.Block)
         .onChildTouchTest((touchinfo) => {
           for(let i = 0; i < touchinfo.length; i++) {
             let info: TouchTestInfo = touchinfo;
             if (info.id == 'SmallCircle' && info.x > 0 && info.y > 0 && this.isTouchPointInCircle(info) == true) {
               Logger.info(TAG, `touchinfo touch point at scope of component: ${info.id}`);
               return { id: 'SmallCircle', strategy: TouchTestStrategy.FORWARD };
             }
             if (info.id == 'BigCircle' && info.x > 0 && info.y > 0 && this.isTouchPointInCircle(info) == true) {
               Logger.info(TAG, `touchinfo touch point at scope of component: ${info.id}`);
               return { id: 'BigCircle', strategy: TouchTestStrategy.FORWARD };
             }
           }
           return { strategy: TouchTestStrategy.DEFAULT };
         })
       }
       .padding({ left: 24, right: 24, bottom: 32 })
       Column() {
         Row() {
           Button({ type: ButtonType.Circle })
             .backgroundColor('#007DFF')
             .width(8)
             .height(8)
           Text($r('app.string.big_circle_prompt'))
             .fontSize(14)
             .fontWeight(400)
             .fontFamily('HarmonyHeiTi')
             .textAlign(TextAlign.Start)
             .margin({ left: 8 })
         }
         .alignItems(VerticalAlign.Center)
         .justifyContent(FlexAlign.Center)

         Row() {
           Button({ type: ButtonType.Circle })
             .backgroundColor('#F7CE00')
             .width(8)
             .height(8)
           Text($r('app.string.small_circle_prompt'))
             .fontSize(14)
             .fontWeight(400)
             .fontFamily('HarmonyHeiTi')
             .textAlign(TextAlign.Start)
             .margin({ left: 8 })
         }
         .alignItems(VerticalAlign.Center)
         .justifyContent(FlexAlign.Center)
       }
     }
     .height('90%')
     .width('100%')
     .alignItems(HorizontalAlign.Center)
     .justifyContent(FlexAlign.Center)
     .flexShrink(1)
   }
   .height('100%')
   .width('100%')
   .backgroundColor($r('app.color.background_shallow_grey'))
  }
}
 
```

### sample仓地址:

**本功能的sample仓地址:**[https://gitee.com/openharmony/applications\_app\_samples/tree/master/code/UI/ArkTsComponentCollection/ComponentCollection](https://gitee.com/openharmony/ap ... ComponentCollection)
[/md]




欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5