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 保护每一次注册操作。掌握这三点,就能安全、稳定地集成手写笔轻捏、双击等专属交互,并结合取色器等高阶功能,为用户提供更流畅的手写笔体验。

相关推荐
是稻香啊2 小时前
HarmonyOS6 ArkTS TimePicker 组件使用文档
harmonyos6
xmdy58662 小时前
Flutter+开源鸿蒙实战|校园易生活Day1 项目初始化搭建+开发环境校验+工程目录规范+第三方库集成+多端屏幕适配+全局底部导航
flutter·开源·harmonyos
想你依然心痛4 小时前
HarmonyOS 6(API 23)实战:打造“空间交互式AR健身私教“——基于Face AR疲劳监测 + Body AR姿态识别的沉浸光感运动系统
ar·restful·harmonyos·悬浮导航·沉浸光感
xmdy58664 小时前
Flutter+开源鸿蒙实战|校园易生活Day2 第三方库批量集成+全局Toast提示+网络状态监听+首页轮播图+资讯卡片布局
flutter·开源·harmonyos
前端不太难4 小时前
为什么说鸿蒙 App 是“状态系统”?
华为·状态模式·harmonyos
SmartBrain4 小时前
Harness 工程建设与 AI 平台建设对比
大数据·人工智能·华为·aigc
●VON4 小时前
猫咪专注 CatFocus 技术博客:一款鸿蒙原生自律计时工具的设计与实现
学习·华为·harmonyos·von·猫咪专注
小雨青年5 小时前
HarmonyOS 原生应用《会议随记 Pro》 V1.3 更新 支持折叠屏、2in1 和 Pura X Max 三形态适配
华为·harmonyos
xmdy586614 小时前
Flutter+开源鸿蒙实战|智联邻里Day9 系统权限适配+应用全局分享+缓存深度优化+版本更新弹窗
flutter·开源·harmonyos