新特性:多模态交互 —— 让应用支持「手势」「语音」与「触感」反馈

📅 2026/7/14 14:59:34
新特性:多模态交互 —— 让应用支持「手势」「语音」与「触感」反馈
文章目录前言一、为什么需要触感反馈1.1 纯视觉反馈的局限1.2 多模态反馈矩阵二、vibrator API 入门2.1 权限声明2.2 导入与基本调用2.3 VibrateEffect 三种类型2.4 HapticFeedback 预设枚举2.5 VibrateAttribute.usage2.6 停止震动三、封装 triggerHaptic语义化触感层四、手势体系Tap / LongPress / Pan4.1 三种基础手势4.2 GestureGroup 互斥模式4.3 左滑删除Stack offset 模式4.4 触感触发时机过阈值再震五、语音交互从 ASR 到指令执行5.1 生产环境路径5.2 指令表设计5.3 executeVoiceCommand 核心逻辑5.4 「按住说话」交互六、综合场景多模态购物车6.1 用户旅程6.2 触感开关6.3 交互日志七、四个实验室场景对照八、踩坑清单8.1 震动无反应8.2 拖动时震动过于频繁8.3 手势冲突点击变成滑动8.4 所有操作同一种震动8.5 usage 混用8.6 语音只做了 UI 没有闭环8.7 Partial 更新 State 数组九、进阶Pattern 自定义节奏十、无障碍与产品策略十一、总结前言移动端交互早已不局限于「看屏幕 点按钮」。用户期望手势左滑删除、长按预览、拖拽排序——操作应自然、跟手语音支付确认、取消订单——解放双手尤其在驾驶、厨电等场景触感点击、成功、失败各有不同的震动反馈——操作「落地」有确认感。三者组合称为多模态交互Multimodal Interaction同一操作在视觉、触觉、听觉或语音通道同时给出反馈降低误操作焦虑提升可用性。HarmonyOS 在 ArkUI 手势体系之上提供了kit.SensorServiceKit的vibrator模块通过startVibration触发马达震动。本文结合项目 Demo从权限配置、震动 API、手势绑定、语音指令流程到综合购物车场景做一次完整实战解析。一、为什么需要触感反馈1.1 纯视觉反馈的局限只有颜色变化或 Toast 提示时用户快速连点时不确定「哪一次点到了」滑动删除过阈值时缺少「已触发」的物理确认支付成功若只有文字缺乏「完成感」。苹果 Human Interface Guidelines 将 Haptic Feedback 列为重要交互层Android 也有Vibrator/HapticFeedbackConstants。HarmonyOS 通过vibrator.startVibration提供系统级能力。1.2 多模态反馈矩阵Demo 中的设计原则操作类型视觉触感语义点击选中边框变蓝 ✓EFFECT_SOFT轻触确认长按预览状态文案EFFECT_HARD强反馈 · 二级操作左滑删除行移除EFFECT_NOTICE_WARNING警告 · 不可逆右滑收藏背景变绿EFFECT_NOTICE_SUCCESS成功 · 正向支付成功金额文案EFFECT_NOTICE_SUCCESS完成支付失败错误提示EFFECT_NOTICE_FAILURE失败核心思想不同语义用不同震动预设用户形成肌肉记忆后甚至不必看屏幕也能感知操作结果。二、vibrator API 入门2.1 权限声明震动需要ohos.permission.VIBRATE。在module.json5的requestPermissions中添加{ name: ohos.permission.VIBRATE }该权限为system_grant类安装时自动授予无需用户弹窗与普通危险权限不同。2.2 导入与基本调用import{vibrator}fromkit.SensorServiceKitimport{BusinessError}fromkit.BasicServicesKitconsttouchAttr:vibrator.VibrateAttribute{usage:touch}constfeedbackAttr:vibrator.VibrateAttribute{usage:physicalFeedback}asyncfunctionvibrateSoft(){consteffect:vibrator.VibratePreset{type:preset,effectId:vibrator.HapticFeedback.EFFECT_SOFT,count:1}awaitvibrator.startVibration(effect,touchAttr)}2.3 VibrateEffect 三种类型type结构用途time{ type: time, duration: number }固定毫秒震动preset{ type: preset, effectId, count }系统预设效果pattern{ type: pattern, pattern }自定义节奏Transient / Continuous2.4 HapticFeedback 预设枚举Demo 用到的预设vibrator.HapticFeedback.EFFECT_SOFT// 轻柔 · 点击vibrator.HapticFeedback.EFFECT_HARD// 硬感 · 长按vibrator.HapticFeedback.EFFECT_NOTICE_SUCCESS// 成功vibrator.HapticFeedback.EFFECT_NOTICE_WARNING// 警告vibrator.HapticFeedback.EFFECT_NOTICE_FAILURE// 失败还可使用EFFECT_SHARP、EFFECT_CLOCK_TIMER等可用isSupportEffectSync(effectId)检测设备是否支持。2.5 VibrateAttribute.usageusage含义Demo 使用场景touch触摸反馈点击、滑动短脉冲physicalFeedback物理/通知反馈成功、失败、警告区分 usage 有助于系统调度马达资源避免与来电震动等冲突。2.6 停止震动awaitvibrator.stopVibration()长按自定义 pattern 或循环震动时需要主动停止预设单次震动一般自动结束。三、封装 triggerHaptic语义化触感层Demo 将震动逻辑收敛为HapticKind枚举 triggerHaptic(kind)enumHapticKind{TAP,SUCCESS,WARNING,ERROR,SWIPE,LONG_PRESS}privateasynctriggerHaptic(kind:HapticKind):Promisevoid{if(!this.hapticEnabled)return// 用户可关闭触感consteffectthis.buildHapticEffect(kind)constattr(kindHapticKind.TAP||kindHapticKind.SWIPE)?TAP_ATTR:FEEDBACK_ATTRawaitvibrator.startVibration(effect,attr)}好处UI 层只关心「这次是什么语义」不关心 effectId全局开关hapticEnabled一处控制错误统一 catch写日志而不 crash。buildHapticEffect映射关系TAP→EFFECT_SOFTSUCCESS→EFFECT_NOTICE_SUCCESSWARNING→EFFECT_NOTICE_WARNINGERROR→EFFECT_NOTICE_FAILURELONG_PRESS→EFFECT_HARDSWIPE→ VibrateTime 40ms四、手势体系Tap / LongPress / Pan4.1 三种基础手势手势典型场景Demo 绑定TapGesture单击选中购物车行 toggle selectedLongPressGesture长按预览/菜单500ms 触发详情PanGesture拖拽/滑动水平 offsetX 左滑删/右滑收藏4.2 GestureGroup 互斥模式同一组件上挂多种手势时用GestureGroup(GestureMode.Exclusive, ...)避免冲突.gesture(GestureGroup(GestureMode.Exclusive,PanGesture({direction:PanDirection.Horizontal,distance:5}).onActionUpdate((event){this.updateCartItem(item.id,{offsetX:event.offsetX})}).onActionEnd((){this.onCartPanEnd(this.findCartItem(item.id))}),LongPressGesture({repeat:false,duration:500}).onAction((){this.onCartLongPress(item)}),TapGesture({count:1}).onAction((){this.onCartTap(item)})))Exclusive表示同一时刻只识别一种手势轻点不会误触发 Pan长按不会和 Tap 打架。4.3 左滑删除Stack offset 模式购物车每一行是经典「底层操作 上层卡片」结构┌─────────────────────────────────┐ │ [删除] [收藏] │ ← 底层 Row红/绿背景 │ ┌───────────────────────────┐ │ │ │ 鸿蒙开发指南 ¥89 ✓ │ │ ← 上层卡片 .offset({ x: offsetX }) │ └───────────────────────────┘ │ └─────────────────────────────────┘onActionUpdate实时更新offsetXonActionEnd判断阈值constSWIPE_THRESHOLD72onCartPanEnd(item:CartItem){if(item.offsetX-SWIPE_THRESHOLD){this.triggerHaptic(HapticKind.WARNING)this.removeCartItem(item.id)// 左滑删除return}if(item.offsetXSWIPE_THRESHOLD){this.triggerHaptic(HapticKind.SUCCESS)this.updateCartItem(item.id,{favorited:true,offsetX:0})return}this.updateCartItem(item.id,{offsetX:0})// 未过阈值回弹}4.4 触感触发时机过阈值再震反模式在onActionUpdate里每次 offset 变化都startVibration——拖动过程中马达狂震体验极差。正模式仅在onActionEnd判定「操作已 commit」时震一次。点击、长按同理在onAction回调里触发。五、语音交互从 ASR 到指令执行5.1 生产环境路径完整语音链路麦克风 → ASR 识别 → NLU 意图解析 → 业务 Handler → TTS 播报 触感HarmonyOS 可接入Core Speech Kit语音识别 / 语音合成。Demo 为降低依赖用模拟 ASR演示流程。5.2 指令表设计constVOICE_COMMANDS[{id:pay,phrase:确认支付,hint:成功反馈 · 下单},{id:cancel,phrase:取消订单,hint:警告反馈 · 撤销},{id:refresh,phrase:刷新列表,hint:轻触反馈 · 重载},{id:help,phrase:我需要帮助,hint:语音播报 · 提示}]每条指令映射识别文案 → 业务动作 → 触感类型。5.3 executeVoiceCommand 核心逻辑executeVoiceCommand(command:VoiceCommand){this.voiceTranscript已识别「${command.phrase}」if(command.idpay){if(this.totalPrice0){this.triggerHaptic(HapticKind.ERROR)// 失败震return}this.triggerHaptic(HapticKind.SUCCESS)// 成功震this.statusText支付成功 · ¥${this.totalPrice}return}// cancel → WARNING, refresh → TAP ...}多模态闭环语音识别结果展示视觉 状态文案视觉 对应预设震动触觉。后续可再加 TTS 播报「支付成功」听觉。5.4 「按住说话」交互语音实验室场景LongPressGesture({repeat:false,duration:300}).onAction((){this.isListeningtruethis.voiceTranscript正在聆听…this.triggerHaptic(HapticKind.TAP)// 开始录音轻触}).onActionEnd((){this.isListeningfalsethis.simulateVoiceInput()// 模拟 ASR 返回})UI 上麦克风圆形按钮变红表示聆听中松手后随机/匹配一条指令并执行——完整走通按住说话 → 识别 → 反馈的产品形态。六、综合场景多模态购物车Demo 默认「综合场景」将三者合一6.1 用户旅程点击商品行 → 选中/取消轻触震 蓝色边框左滑某行 → 删除警告震 行消失右滑某行 → 收藏成功震 绿色底层长按某行 → 预览价格强震 状态文案点击「语音支付」或说「确认支付」→ 成功震 支付文案未选中商品就支付 →失败震 错误提示。6.2 触感开关顶部Toggle控制hapticEnabled开启所有操作带震动关闭仅视觉 日志方便对比和 accessibility 场景部分用户禁用震动。6.3 交互日志feedbackLogs记录每条操作的通道手势/语音/触感与时间便于调试11:05:32 [手势] Tap · 鸿蒙开发指南 11:05:35 [触感] EFFECT_SOFT · touch 11:05:40 [手势] SwipeLeft 删除 · ArkTS 实战手册 11:05:40 [触感] EFFECT_NOTICE_WARNING 11:05:45 [语音] 确认支付 ¥89 11:05:45 [触感] EFFECT_NOTICE_SUCCESS七、四个实验室场景对照场景重点适合学习综合场景手势语音触感联动产品级交互设计触感实验室六种预设 时长滑块vibrator API手势实验室Exclusive 手势组Tap/LongPress/Pan语音实验室按住说话 指令列表ASR 流程占位八、踩坑清单8.1 震动无反应检查module.json5是否声明VIBRATE权限模拟器可能不支持马达需真机验证catchBusinessErrorcode801表示能力不支持201表示权限拒绝。8.2 拖动时震动过于频繁不要在onActionUpdate里触发震动仅在onActionEnd或操作 commit 时震一次。8.3 手势冲突点击变成滑动使用GestureGroup(Exclusive)Pan 设置合理distance如 5vp避免轻微抖动识别为 Pan。8.4 所有操作同一种震动用户无法区分成功/失败按语义映射不同HapticFeedback预设。8.5 usage 混用点击类用touch通知/结果类用physicalFeedback与系统场景保持一致减少被系统降权或打断的概率。8.6 语音只做了 UI 没有闭环识别结果要有业务副作用改状态、跳转、提交必须配合触感或 TTS否则用户不确定是否生效。8.7 Partial 更新 State 数组ArkTS 中更新cartItems某一项时需immutable 替换整个数组Demo 的updateCartItem模式否则 UI 可能不刷新。九、进阶Pattern 自定义节奏除 preset 外可用VibratorPatternBuilder构造复杂节奏项目HapticEngine.ets中有完整示例constbuildernewvibrator.VibratorPatternBuilder()builder.addTransientEvent(0,{intensity:90,frequency:120})builder.addTransientEvent(90,{intensity:70,frequency:100})constpatternbuilder.build()consteffect:vibrator.VibrateFromPattern{type:pattern,pattern:pattern}awaitvibrator.startVibration(effect,feedbackAttr)适用心跳提醒、双击确认、游戏技能反馈等需要节奏感的场景。十、无障碍与产品策略系统设置用户可在系统层关闭触感App 内 Toggle 是补充而非替代可配置设置页提供「触感强度/开关」是成熟 App 标配不要滥用列表滚动、hover 不需要震关键 commit 点才震与 Sound 配合静音模式下触感更重要响铃模式下可减弱。十一、总结模态核心 APIDemo 要点触感vibrator.startVibration语义化 HapticKind usage 区分手势Tap / LongPress / Pan GestureGroup左滑删/右滑收藏过阈值再震语音指令表 executeVoiceCommand模拟 ASR成功/失败不同震一句话多模态不是把三种能力堆在一起而是同一操作、多通道一致反馈——眼看到状态变化手感到确认震动耳或屏听到/看到语义结果。把 Demo 跑在真机上选中商品时轻震一下左滑删除时警告震语音支付成功时 success 震——这种「操作落地感」就是vibrator与手势事件结合的价值。