【鸿蒙实战开发】ArkUI-交互事件详解

151 篇文章 0 订阅
151 篇文章 1 订阅

前言

通用事件按照触发类型来分类,包括触屏事件、键鼠事件、焦点事件和拖拽事件。

  • 触屏事件:手指或手写笔在触屏上的单指或单笔操作。

  • 键鼠事件:包括外设鼠标或触控板的操作事件和外设键盘的按键事件。

    • 鼠标事件是指通过连接和使用外设鼠标/触控板操作时所响应的事件。
    • 按键事件是指通过连接和使用外设键盘操作时所响应的事件。
  • 焦点事件:通过以上方式控制组件焦点的能力和响应的事件。

  • 拖拽事件:由触屏事件和键鼠事件发起,包括手指/手写笔长按组件拖拽和鼠标拖拽。

  • 事件分发:描述触控类事件(不包括按键,焦点)响应链的命中收集过程。

手势事件由绑定手势方法和绑定的手势组成,绑定的手势可以分为单一手势和组合手势两种类型,根据手势的复杂程度进行区分。

  • 绑定手势方法:用于在组件上绑定单一手势或组合手势,并声明所绑定的手势的响应优先级。

  • 单一手势:手势的基本单元,是所有复杂手势的组成部分。

  • 组合手势:由多个单一手势组合而成,可以根据声明的类型将多个单一手势按照一定规则组合成组合手势,并进行使用。

概述

ArkUI触控事件,根据输入源不同,主要划分为touch类与mouse类。

touch类的输入源包含:finger、pen

mouse类的输入源包含:mouse、touchpad、joystick

由这两类输入源可以触发如下事件:

touchmouse
触摸事件触摸事件
点击事件鼠标事件
拖拽事件点击事件
手势事件拖拽事件
手势事件

无论是touch类事件还是mouse类事件,在ArkUI框架上均由触摸测试发起,触摸测试直接决定了ArkUI事件响应链的生成及事件的分发。

触摸测试

如下是对触摸测试结果影响较大的几个因素:

  • TouchTest:触摸测试入口方法,此方法无外部接口

  • hitTestBehavior:触摸测试控制

  • interceptTouch:事件自定义拦截

  • responseRegion:触摸热区设置

  • enabled:禁用控制

  • 安全组件

  • 其他属性设置:透明度/组件下线

TouchTest

  • TouchTest的触发时机由每次点按的按下动作发起,默认由组件树的根节点TouchTest方法作为入口。

  • hitTestBehavior可以由InterceptTouch事件变更。

  • 触摸热区/禁用控制/透明度等不满足组件事件交互诉求,会导致立即返回父节点。

image.png

触摸测试控制

具体用法参考触摸测试控制

  • 命中:触摸测试成功收集到当前组件/子组件的事件。

  • 子组件对父组件触摸测试的影响,取决于最后一个没有被阻塞触摸测试的子组件。

  • HitTestMode.Default:默认不配hitTestBehavior属性的效果,自身如果命中会阻塞兄弟,但是不阻塞孩子。

image.png

  • HitTestMode.None:自身不接收事件,但不会阻塞兄弟/孩子继续做触摸测试。
    image.png

  • HitTestMode.Block:阻塞孩子的触摸测试,如果自身触摸测试命中,会阻塞兄弟及父亲的触摸测试。

image.png

  • HitTestMode.Transparent:自身进行触摸测试,同时不阻塞兄弟及父亲。

image.png

触屏事件

自定义事件拦截

自定义事件拦截在按下触发时,可以根据业务状态动态改变组件的hitTestBehavior属性。

禁用控制

设置禁用控制的组件,包括其子组件不会发起触摸测试过程,会直接返回父节点继续触摸测试。

触摸热区设置

触摸热区设置会影响触屏/鼠标类的触摸测试,如果设置为0,或不可触控区域,则事件直接返回父节点继续触摸测试。

安全组件

ArkUI包含的安全组件有:使用位置组件使用粘贴组件使用保存组件等。

安全组件当前对触摸测试影响:如果有组件z序比安全组件靠前,且遮盖安全组件,则安全组件事件直接返回到父节点继续触摸测试。

事件响应链的收集

ArkUI事件响应链收集,根据右子树(按组件布局的先后层级)优先的后序遍历流程,流程为:

foreach(item=>(node.rbegin(),node.rend(){
    item.TouchTest()
}
node.collectEvent()

响应链收集举例,按下图的组件树,hitTestBehavior属性均为默认,用户点按的动作如果发生在组件5上,则最终收集到的响应链,以及先后关系是5,3,1。

因为组件3的hitTestBehavior属性为Default,收集到事件后会阻塞兄弟节点,所以没有收集组件1的左子树。

image.png
触屏事件指当手指/手写笔在组件上按下、滑动、抬起时触发的回调事件。包括点击事件拖拽事件触摸事件

图1 触摸事件原理

image.png

点击事件

点击事件是指通过手指或手写笔做出一次完整的按下和抬起动作。当发生点击事件时,会触发以下回调函数:

onClick(event: (event?: ClickEvent) => void)

event参数提供点击事件相对于窗口或组件的坐标位置,以及发生点击的事件源。

例如通过按钮的点击事件控制图片的显示和隐藏。

@Entry
@Component
struct IfElseTransition {
  @State flag: boolean = true;
  @State btnMsg: string = 'show';

  build() {
    Column() {
      Button(this.btnMsg).width(80).height(30).margin(30)
        .onClick(() => {
          if (this.flag) {
            this.btnMsg = 'hide';
          } else {
            this.btnMsg = 'show';
          }
          // 点击Button控制Image的显示和消失
          this.flag = !this.flag;
        })
      if (this.flag) {
        Image($r('app.media.icon')).width(200).height(200)
      }
    }.height('100%').width('100%')
  }
}

图2 通过按钮的点击事件控制图片的显示和隐藏

0000000000011111111.20240807205237.36278603937271392857640075479630.gif

触摸事件

当手指或手写笔在组件上触碰时,会触发不同动作所对应的事件响应,包括按下(Down)、滑动(Move)、抬起(Up)事件:

onTouch(event: (event?: TouchEvent) => void)
  • event.type为TouchType.Down:表示手指按下。

  • event.type为TouchType.Up:表示手指抬起。

  • event.type为TouchType.Move:表示手指按住移动。

  • event.type为TouchType.Cancel:表示打断取消当前手指操作。

触摸事件可以同时多指触发,通过event参数可获取触发的手指位置、手指唯一标志、当前发生变化的手指和输入的设备源等信息。

// xxx.ets
@Entry
@Component
struct TouchExample {
  @State text: string = '';
  @State eventType: string = '';

  build() {
    Column() {
      Button('Touch').height(40).width(100)
        .onTouch((event?: TouchEvent) => {
          if(event){
            if (event.type === TouchType.Down) {
              this.eventType = 'Down';
            }
            if (event.type === TouchType.Up) {
              this.eventType = 'Up';
            }
            if (event.type === TouchType.Move) {
              this.eventType = 'Move';
            }
            this.text = 'TouchType:' + this.eventType + '\nDistance between touch point and touch element:\nx: '
            + event.touches[0].x + '\n' + 'y: ' + event.touches[0].y + '\nComponent globalPos:('
            + event.target.area.globalPosition.x + ',' + event.target.area.globalPosition.y + ')\nwidth:'
            + event.target.area.width + '\nheight:' + event.target.area.height
          }
        })
      Button('Touch').height(50).width(200).margin(20)
        .onTouch((event?: TouchEvent) => {
          if(event){
            if (event.type === TouchType.Down) {
              this.eventType = 'Down';
            }
            if (event.type === TouchType.Up) {
              this.eventType = 'Up';
            }
            if (event.type === TouchType.Move) {
              this.eventType = 'Move';
            }
            this.text = 'TouchType:' + this.eventType + '\nDistance between touch point and touch element:\nx: '
            + event.touches[0].x + '\n' + 'y: ' + event.touches[0].y + '\nComponent globalPos:('
            + event.target.area.globalPosition.x + ',' + event.target.area.globalPosition.y + ')\nwidth:'
            + event.target.area.width + '\nheight:' + event.target.area.height
          }
        })
      Text(this.text)
    }.width('100%').padding(30)
  }
}

0000000000011111111.20240807205237.60286768073277158620574011558770.gif

写在最后

●如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
●点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
●关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
●更多鸿蒙最新技术知识点,请移步前往小编:https://gitee.com/

在这里插入图片描述

  • 38
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值