HarmonyOS Pen Kit 实战:手写笔轻捏、双击与取色器完整集成

文章目录

    • 前言
    • [一、Pen Kit 基础概念](#一、Pen Kit 基础概念)
      • [1.1 模块构成](#1.1 模块构成)
      • [1.2 支持的事件类型](#1.2 支持的事件类型)
    • 二、回调引用管理
      • [2.1 为什么要保存回调引用](#2.1 为什么要保存回调引用)
      • [2.2 初始化回调的时机](#2.2 初始化回调的时机)
    • 三、事件注册与取消
      • [3.1 注册监听](#3.1 注册监听)
      • [3.2 取消监听](#3.2 取消监听)
      • [3.3 事件对象字段](#3.3 事件对象字段)
    • 四、取色器的集成
      • [4.1 工作原理](#4.1 工作原理)
      • [4.2 返回值说明](#4.2 返回值说明)
    • [五、UI 状态反馈设计](#五、UI 状态反馈设计)
      • [5.1 监听状态的可视化](#5.1 监听状态的可视化)
      • [5.2 事件计数器](#5.2 事件计数器)
      • [5.3 Toast 即时反馈](#5.3 Toast 即时反馈)
    • 六、完整生命周期流程
    • 总结

前言

随着华为平板与触控笔生态的不断完善,M-Pencil 已经成为 HarmonyOS 设备上重要的输入方式之一。开发者不仅可以监听普通触摸事件,还能通过官方 Pen Kit 捕获手写笔特有的交互行为------例如笔身轻捏、悬停双击,以及结合取色器实现更丰富的创作功能。

本文以一个完整的手写笔事件测试页面为例,详细拆解 stylusInteraction 模块的注册原理、回调管理技巧,以及 imageFeaturePicker 取色器的调用方式,帮助你快速在实际项目中集成手写笔交互能力。

HarmonyOS Pen Kit 手写笔交互概览 --- M-Pencil 悬停状态下支持轻捏(squeeze)与双击(doubleTap)两种专属事件,并可结合取色器实现颜色拾取功能*

一、Pen Kit 基础概念

1.1 模块构成

HarmonyOS 的 Pen Kit(@kit.Penkit)主要包含两个核心模块:

模块 说明 典型用途
stylusInteraction 手写笔专属交互事件 监听轻捏、双击等笔身操作
imageFeaturePicker 图像取色器 在屏幕指定位置拾取颜色值

两个模块相互独立,可以单独使用,也可以结合使用,构建完整的手写笔辅助工具。

Pen Kit 模块架构 --- stylusInteraction 负责手写笔交互事件监听,imageFeaturePicker 提供屏幕取色能力,两者可独立或组合使用*

1.2 支持的事件类型

stylusInteraction 目前提供以下两种事件:

事件名 触发方式 回调类型
squeeze 笔处于悬停状态时轻捏笔身按钮 SqueezeEvent
doubleTap 笔处于悬停状态时双击笔身 DoubleTapEvent

提示:两种事件都要求手写笔处于悬停(hover)状态,即笔尖靠近但未完全按压屏幕时才能触发,普通点击状态下不会响应。

二、回调引用管理

2.1 为什么要保存回调引用

这是使用 stylusInteraction 时最容易踩坑的地方。

stylusInteraction.on() 注册监听,stylusInteraction.off() 取消监听。取消时必须传入与注册时完全相同的函数引用,否则取消操作不会生效,造成内存泄漏或重复触发。

typescript 复制代码
// 在组件属性中声明,保存引用
private squeezeCallback: (event: stylusInteraction.SqueezeEvent) => void = () => {};
private doubleTapCallback: (event: stylusInteraction.DoubleTapEvent) => void = () => {};

aboutToAppear 中完成初始化赋值,之后注册和取消都使用这两个属性,而不是重新创建匿名函数。

提示:如果直接在 on() 中写 () => {} 匿名函数,后续 off() 传入另一个匿名函数时,两者是不同引用,取消会静默失败。

回调引用管理的正确与错误方式对比 --- 左侧每次创建匿名函数导致引用不匹配、取消失败;右侧将回调保存为成员属性后,注册与取消使用同一引用,配对可靠*

2.2 初始化回调的时机

生命周期 作用
aboutToAppear 初始化回调函数引用(赋值给成员属性)
onPageShow 注册事件监听(页面可见时开始监听)
onPageHide 取消事件监听(页面不可见时释放)
aboutToDisappear 兜底取消监听(防止页面销毁时资源未释放)

这种分层设计的好处是:当用户切到其他页面时,后台页面不会继续消耗资源处理笔的事件;回到页面后自动恢复监听,体验无感知。

三、事件注册与取消

3.1 注册监听

注册时使用 try-catch 包裹是必要的。设备不支持手写笔、权限未授予等情况都会抛出异常,如果不捕获会导致应用崩溃。

typescript 复制代码
stylusInteraction.on('squeeze', this.squeezeCallback);
stylusInteraction.on('doubleTap', this.doubleTapCallback);

两个事件分别用独立的 try-catch 块处理,确保一个注册失败不影响另一个。注册成功后将 isListening 标志置为 true,方便后续判断当前监听状态。

3.2 取消监听

typescript 复制代码
stylusInteraction.off('squeeze', this.squeezeCallback);
stylusInteraction.off('doubleTap', this.doubleTapCallback);

取消前先检查 isListening 标志,避免在从未成功注册的情况下执行无意义的取消操作。取消完成后将标志置回 false

3.3 事件对象字段

两种事件的回调对象均包含以下核心字段:

字段 类型 含义
timestamp number 事件发生的时间戳(毫秒)

可以将 timestamp 用于计算两次操作的时间间隔,或者在 UI 上展示最近一次操作的时刻。

四、取色器的集成

4.1 工作原理

imageFeaturePicker.pickForResult() 接收屏幕上某个点的坐标,系统会弹出取色器浮层,让用户确认拾取位置,最终以 Promise 形式返回颜色信息。

关键点在于坐标的来源。按钮的 onClick 回调携带了一个 ClickEvent 对象,其中 event.displayXevent.displayY 是点击位置在屏幕坐标系 中的绝对坐标,恰好符合 pickForResult 的参数要求。

typescript 复制代码
.onClick((event) => {
    imageFeaturePicker.pickForResult(event.displayX, event.displayY)
        .then((colorInfo: imageFeaturePicker.PickedColorInfo) => {
            // colorInfo.color 即拾取到的颜色值
        })
        .catch((err: BusinessError) => {
            // 处理用户取消或设备不支持的情况
        });
})

4.2 返回值说明

PickedColorInfo 对象包含的主要字段:

字段 说明
color 拾取到的颜色值,通常为十六进制字符串(如 #FF5733

提示:用户点击取消按钮时,Promise 会进入 catch 分支,err.code 会是特定的取消错误码,需要在 catch 中区分"用户主动取消"和"真实错误",避免把取消操作误报为失败。

五、UI 状态反馈设计

5.1 监听状态的可视化

页面底部通过一行文字实时展示监听状态,颜色区分运行中与已停止:

  • 绿色(#00C853):监听运行中,手写笔事件可以被捕获
  • 红色(#FF5252):监听已停止,通常是页面切换到后台时的状态

这种设计在调试阶段非常实用,可以直观确认监听是否正常工作。

5.2 事件计数器

页面维护了两个独立的计数器变量:

  • squeezeCount:记录轻捏事件的累计次数
  • doubleTapCount:记录双击事件的累计次数

每次事件触发时同步更新 lastEventInfo,展示最新一次事件的类型和时间戳,方便快速判断事件是否正常响应。

提供"重置计数器"按钮将两个计数清零,适合在多轮测试之间清空历史数据,保证测试结果的准确性。

5.3 Toast 即时反馈

每次捕获到手写笔事件时,通过 getUIContext().getPromptAction().showToast() 弹出短暂提示。

主要特点:

  1. 在 V2 组件体系或普通页面中,getUIContext() 是获取 UI 上下文的推荐方式,避免直接使用全局 promptAction
  2. duration 设置为 1500ms,时间较短,不会遮挡后续操作
  3. 消息内容包含当前计数,让用户能立刻看到本次是第几次触发

六、完整生命周期流程

整个页面的生命周期管理可以用以下流程来理解:

Pen Kit 事件监听的完整生命周期 --- 从初始化到销毁的全流程,含页面重新进入时的循环恢复机制*

  1. 页面创建(aboutToAppear):初始化回调函数引用,此时还未注册监听
  2. 页面显示(onPageShow):注册 squeezedoubleTap 两个监听,isListening 置为 true
  3. 用户操作手写笔:事件回调触发,计数器自增,UI 更新,Toast 弹出
  4. 页面隐藏(onPageHide):取消两个监听,isListening 置为 false,停止资源消耗
  5. 再次进入页面(onPageShow):重新注册监听,无缝恢复
  6. 页面销毁(aboutToDisappear):兜底执行一次取消,防止泄漏

核心优势:

  • 监听与页面可见性严格绑定,后台不耗资源
  • 回调引用固定保存,注册与取消配对可靠
  • 每个注册/取消操作独立 try-catch,单点失败不影响整体

总结

HarmonyOS Pen Kit 的核心使用模式可以归纳为三点:aboutToAppear 中保存回调引用、在页面生命周期中配对注册与取消、用 try-catch 保护每一次注册操作。掌握这三点,就能安全、稳定地集成手写笔轻捏、双击等专属交互,并结合取色器等高阶功能,为用户提供更流畅的手写笔体验。

相关推荐
博客-小覃20 小时前
Zabbix之华为交换机的日志记录信息操作详细教程
服务器·网络·华为·zabbix
不羁的木木1 天前
Form Kit(卡片开发服务)学习笔记01-核心概念与架构设计
笔记·学习·harmonyos
不羁的木木1 天前
ArkWeb实战学习笔记01-核心概念与架构设计
笔记·学习·harmonyos
Goway_Hui1 天前
【鸿蒙原生应用开发--ArkUI--010】Recipe-app 菜谱应用开发教程
华为·harmonyos
●VON1 天前
鸿蒙 BodyAR 实战:基于人体骨骼追踪的体感运动计数器开发全解
华为·ar·harmonyos·鸿蒙·新特性
Davina_yu1 天前
页面路由导航:Router与Navigation组件的跳转传参(7)
harmonyos·鸿蒙·鸿蒙系统
Ww.xh1 天前
鸿蒙WebView IPC防伪造请求方案
华为·harmonyos
大雷神1 天前
第25篇|Surface 预览控制:ArkUI 页面如何接住相机画面
harmonyos
大雷神1 天前
第24篇|相机权限和设备枚举:先判断能力再打开预览
harmonyos
川石课堂软件测试1 天前
使用mock进行接口测试教程
数据库·python·功能测试·测试工具·华为·单元测试·appium