ArkUI 输入事件:手指、鼠标、键盘不是一回事

举报
蓝瘦的蜕变 发表于 2026/10/13 17:52:35 2026/10/13
【摘要】 今天我们做一个输入事件观察页,看 onTouch、onHover、onMouse 和 onKeyEvent 分别适合什么。 同一个页面在手机、平板、2in1 设备上,输入来源可能完全不同。手指更关心触摸动作,鼠标有悬停和按键,键盘还要先处理焦点。我们先用最小 Demo 看清楚它们的差别。 参考文档: https://d

ArkUI 输入事件:手指、鼠标、键盘不是一回事

今天我们做一个输入事件观察页,看 onTouch、onHover、onMouse 和 onKeyEvent 分别适合什么。

同一个页面在手机、平板、2in1 设备上,输入来源可能完全不同。手指更关心触摸动作,鼠标有悬停和按键,键盘还要先处理焦点。我们先用最小 Demo 看清楚它们的差别。

参考文档:

  • https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-interaction-development-guide-overview

触摸事件看的是屏幕动作

.onTouch((event: TouchEvent) => {
  this.touchText = `Touch type: ${event.type}`
})

onTouch 更贴近手指操作。它适合区分按下、移动、抬起这类原始触摸动作。普通按钮点击不一定要用它,按钮用 onClick 更直接。

鼠标有悬停,也有点击动作

.onHover((isHover: boolean, event: HoverEvent) => {
  this.hoverText = isHover ? '鼠标移入了 Hover 区域' : '鼠标移出了 Hover 区域'
})

onHover 只关心移入和移出。它适合做悬停高亮、提示入口、桌面端辅助反馈。

.onMouse((event: MouseEvent) => {
  this.mouseText = `Mouse action: ${event.action}, button: ${event.button}`
})

onMouse 能拿到鼠标动作和按钮。这里我们只展示结果,不做复杂右键菜单。

键盘事件先要有焦点

.focusable(true)
.focusOnTouch(true)
.onKeyEvent((event: KeyEvent): boolean => {
  this.keyText = `Key type: ${event.type}, keyCode: ${event.keyCode}`
  return true
})

键盘事件最容易被忽略的一点是:组件通常要能获得焦点。Demo 里用了 focusable(true) 和 focusOnTouch(true),让你点到区域后再按键。

你现在做的页面主要面向手指操作,还是也会被鼠标和键盘使用?这个判断会影响你一开始怎么设计交互。

完整示例代码

文件位置:entry/src/main/ets/pages/arkUI/interaction/ArkUIInputEventDemo.ets

@Entry
@Component
struct ArkUIInputEventDemo {
  @State touchText: string = '触摸区域还没有收到事件'
  @State hoverText: string = '鼠标还没有移入'
  @State mouseText: string = '鼠标还没有点击'
  @State keyText: string = '让下面的区域获得焦点后按键'

  private showTip(message: string): void {
    this.getUIContext().getPromptAction().showToast({
      message: message,
      duration: 1200,
      bottom: 120
    })
  }

  @Builder
  sectionTitle(title: string, desc: string) {
    Column({ space: 6 }) {
      Text(title)
        .fontSize(19)
        .fontWeight(FontWeight.Bold)
        .fontColor('#111827')
      Text(desc)
        .fontSize(13)
        .fontColor('#6B7280')
        .lineHeight(20)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  eventPanel(title: string, desc: string, color: string) {
    Column({ space: 10 }) {
      Text(title)
        .fontSize(17)
        .fontWeight(FontWeight.Bold)
        .fontColor(color)
      Text(desc)
        .fontSize(13)
        .fontColor('#4B5563')
        .lineHeight(20)
    }
    .width('100%')
    .padding(16)
    .borderRadius(14)
    .backgroundColor('#FFFFFF')
    .border({ width: 1, color: '#E5E7EB' })
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Scroll() {
      Column({ space: 22 }) {
        Column({ space: 8 }) {
          Text('ArkUI 输入事件')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
          Text('手指、鼠标、键盘不是一回事')
            .fontSize(16)
            .fontColor('#4B5563')
          Text('同一个页面可能被手指、鼠标、键盘操作。我们先用几个小面板看清楚输入来源。')
            .fontSize(14)
            .fontColor('#6B7280')
            .lineHeight(22)
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        this.sectionTitle('触摸事件:更贴近屏幕操作', 'onTouch 能拿到触摸动作,适合需要区分按下、移动和抬起的场景。')
        Column() {
          this.eventPanel('触摸区域', '按一下或滑过这块区域,下面会显示最近一次触摸类型。', '#2563EB')
          Text(this.touchText)
            .fontSize(13)
            .fontColor('#111827')
            .lineHeight(20)
            .padding(12)
            .borderRadius(10)
            .backgroundColor('#F8FAFC')
            .width('100%')
        }
        .width('100%')
        .onTouch((event: TouchEvent) => {
          this.touchText = `Touch type: ${event.type}`
          this.showTip('收到触摸事件')
        })

        this.sectionTitle('悬停和鼠标:桌面设备更常见', 'onHover 关心是否移入,onMouse 关心鼠标动作。')
        Row({ space: 12 }) {
          Column() {
            this.eventPanel('Hover', '鼠标移入或移出这里。', '#0F766E')
            Text(this.hoverText)
              .fontSize(13)
              .fontColor('#111827')
              .lineHeight(20)
              .padding(12)
              .borderRadius(10)
              .backgroundColor('#F8FAFC')
              .width('100%')
          }
          .layoutWeight(1)
          .onHover((isHover: boolean, event: HoverEvent) => {
            this.hoverText = isHover ? '鼠标移入了 Hover 区域' : '鼠标移出了 Hover 区域'
          })

          Column() {
            this.eventPanel('Mouse', '鼠标点击这里。', '#C2410C')
            Text(this.mouseText)
              .fontSize(13)
              .fontColor('#111827')
              .lineHeight(20)
              .padding(12)
              .borderRadius(10)
              .backgroundColor('#F8FAFC')
              .width('100%')
          }
          .layoutWeight(1)
          .onMouse((event: MouseEvent) => {
            this.mouseText = `Mouse action: ${event.action}, button: ${event.button}`
            this.showTip('收到鼠标事件')
          })
        }
        .width('100%')
        .alignItems(VerticalAlign.Top)

        this.sectionTitle('键盘事件:先让组件能获得焦点', '键盘事件通常需要组件可聚焦,真实项目里还要考虑焦点顺序。')
        Column() {
          this.eventPanel('键盘区域', '点击这块区域后按任意键,观察 keyCode。', '#7C3AED')
          Text(this.keyText)
            .fontSize(13)
            .fontColor('#111827')
            .lineHeight(20)
            .padding(12)
            .borderRadius(10)
            .backgroundColor('#F8FAFC')
            .width('100%')
        }
        .width('100%')
        .focusable(true)
        .focusOnTouch(true)
        .onKeyEvent((event: KeyEvent): boolean => {
          this.keyText = `Key type: ${event.type}, keyCode: ${event.keyCode}`
          this.showTip('收到键盘事件')
          return true
        })
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F8FAFC')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。