【HarmonyOS 7新能力|046】智慧手势工程封装:把接入逻辑放进可维护的分层结构

【HarmonyOS 7新能力|046】智慧手势工程封装:把接入逻辑放进可维护的分层结构

滑动、长按、捏合等输入看似简单,但同一轨迹在不同页面、控件和用户目标下可能代表完全不同的动作。若识别结果直接触发删除、提交或跳转,偶发误判就会变成实际损失。智慧手势的工程重点不是追求一个漂亮的识别准确率,而是把原始事件、手势候选、业务上下文、意图置信度和可撤销动作组成受控闭环。

说明:本文的 GestureInputPortIntentResolver 等为教学抽象,不是 HarmonyOS SDK 的真实接口。手势能力、设备支持、权限和 API 签名请以当前官方文档与目标 SDK 为准。

1. 区分手势、意图与动作

手势描述输入模式,例如向左滑;意图表达用户想做什么,例如查看下一项;动作才是应用执行的命令。三者分开后,同一手势可以按页面上下文映射不同意图,也可以在高风险动作前追加确认。

ts 复制代码
export interface GestureCandidate {
  type: 'tap' | 'longPress' | 'swipe' | 'pinch' | 'custom'
  confidence: number
  direction?: 'left' | 'right' | 'up' | 'down'
  magnitude?: number
  occurredAt: number
}

export interface IntentCandidate {
  name: string
  confidence: number
  reversible: boolean
}

识别层不接触业务服务,动作层也不读取原始触点。

2. 四层架构建立输入边界

交互页面负责可视反馈与常规控件;手势编排层完成候选融合、冲突仲裁和动作映射;输入能力适配层统一触摸、传感或平台手势事件;手势与动作仓库保存配置、阈值和短期执行状态。

ts 复制代码
export interface GestureInputPort {
  subscribe(listener: (event: NormalizedInputEvent) => void): Unsubscribe
  capability(): Promise<InputCapability>
}

export interface GesturePolicyStore {
  policyFor(sceneId: string): Promise<GesturePolicy>
  actionFor(intent: string): Promise<ActionDescriptor | undefined>
}

页面不能直接修改识别阈值,适配器也不能调用业务命令。

3. 原始事件先归一化

不同设备的坐标、采样频率和输入方式可能不同。适配层把它们转换为统一事件,带设备类别、时间戳、坐标范围和有效性标记。

ts 复制代码
export interface NormalizedInputEvent {
  sequenceId: string
  pointerId: number
  phase: 'start' | 'move' | 'end' | 'cancel'
  xRatio: number
  yRatio: number
  pressure?: number
  source: 'touch' | 'mouse' | 'pen' | 'sensor'
  timestamp: number
}

无效或乱序事件在此层丢弃,业务日志不记录可还原用户行为的完整轨迹。

4. 手势识别输出候选集合

复杂轨迹可能同时符合滑动和拖拽。识别器不急于选唯一结果,而是生成带置信度的候选集合,保留时间、方向与幅度等必要特征。

ts 复制代码
export interface GestureRecognitionResult {
  sequenceId: string
  candidates: readonly GestureCandidate[]
  completed: boolean
  cancelled: boolean
}

function bestCandidate(result: GestureRecognitionResult): GestureCandidate | undefined {
  return [...result.candidates].sort((a, b) => b.confidence - a.confidence)[0]
}

置信度只表示识别证据,不代表业务动作可以直接执行。

5. 智慧手势意图闭环

流程从事件采样开始,经过手势识别、上下文融合和意图判断,再进行动作确认与效果反馈。低置信度、手势冲突和用户取消进入异常旁路,不强行执行。

ts 复制代码
export type IntentResolution =
  | { status: 'resolved'; intent: IntentCandidate }
  | { status: 'ambiguous'; alternatives: readonly IntentCandidate[] }
  | { status: 'ignored'; reason: string }

模糊结果可以提示用户使用显式控件,而不是反复猜测。

6. 上下文只提供必要信息

意图判断需要知道当前页面、焦点控件、是否编辑、可用动作和用户偏好,但不应读取页面全部对象。构造窄上下文,让规则可测试。

ts 复制代码
export interface GestureContext {
  sceneId: string
  focusedControl?: string
  editing: boolean
  availableActions: readonly string[]
  accessibilityMode: boolean
  orientation: 'portrait' | 'landscape'
}

上下文快照与手势序列绑定,页面变化后旧判断不能继续执行。

7. 冲突仲裁遵守显式优先级

子组件拖拽、父容器滚动和系统返回手势可能竞争。策略表定义作用区域、方向、最小幅度、优先级与是否允许同时识别。

ts 复制代码
export interface GestureRule {
  id: string
  sceneId: string
  gestureType: GestureCandidate['type']
  region?: RectRatio
  priority: number
  exclusive: boolean
  mappedIntent: string
}

function arbitrate(matches: GestureRule[]): GestureRule | undefined {
  return [...matches].sort((a, b) => b.priority - a.priority)[0]
}

系统导航边缘和无障碍操作优先级不能被普通业务手势覆盖。

8. 置信阈值按动作风险分级

浏览下一张与删除内容的风险不同。低风险、可撤销动作可以采用较低阈值并立即反馈;不可逆动作要求更高置信度与显式确认。

ts 复制代码
export interface ActionDescriptor {
  id: string
  risk: 'low' | 'medium' | 'high'
  reversible: boolean
  confirmationRequired: boolean
}

export function requiredConfidence(action: ActionDescriptor): number {
  if (action.risk === 'high') return 0.95
  if (action.risk === 'medium') return 0.85
  return 0.7
}

数值仅为结构示例,实际阈值必须经真实场景测试确定。

9. 动作执行使用命令与幂等键

识别成功后生成业务命令,包含序列 ID、上下文版本和动作参数。执行器以命令 ID 去重,避免重复回调导致动作执行两次。

ts 复制代码
export interface GestureCommand {
  commandId: string
  sequenceId: string
  actionId: string
  contextRevision: number
  params: Record<string, string>
}

async function executeOnce(command: GestureCommand): Promise<ActionResult> {
  const known = await actionStore.find(command.commandId)
  if (known) return known
  return actionExecutor.execute(command)
}

执行前再次校验页面上下文仍有效,否则取消。

10. 可撤销动作先保留补偿

移动、归档、隐藏等动作可以在短时间内提供撤销。执行记录保存补偿命令和有效期;删除等不可逆操作则在执行前使用明确确认。

ts 复制代码
export interface ReversibleActionRecord {
  commandId: string
  actionId: string
  compensation: GestureCommand
  undoExpiresAt: number
  state: 'applied' | 'undone' | 'expired'
}

撤销按钮是可访问的普通控件,不能要求用户再做一个复杂手势才能恢复。

11. 无障碍与多输入设备兼容

智慧手势只能是增强路径,核心功能仍应提供按钮、键盘或其他可访问入口。屏幕阅读、放大模式或运动能力受限时,策略可以禁用冲突手势并增加反馈。

ts 复制代码
export interface InputFallback {
  actionId: string
  visibleControlId: string
  keyboardShortcut?: string
  voiceLabel?: string
}

鼠标、触控笔和触摸的阈值分别验证,不假设轨迹特征完全相同。

12. 验收清单与总结

测试覆盖短滑、慢拖、多指、边缘手势、连续输入、页面切换、方向变化和输入取消;验证冲突仲裁稳定、低置信结果不执行、高风险动作要求确认、重复回调幂等、撤销可用。还要在无障碍模式和多种输入设备上确认核心功能有替代入口。

智慧手势的工程价值,不是替用户猜得更多,而是在明确边界内提供更自然的快捷交互。通过输入归一化、候选识别、上下文融合、风险阈值、冲突仲裁和可撤销命令,系统既能利用意图推断,也能在不确定时安全地退回显式交互。

相关推荐
贾伟康1 小时前
【HarmonyOS 7新能力|050】Core File Kit mmap工程封装:把接入逻辑放进可维护的分层结构
性能优化·harmonyos·arkts·文件系统·mmap
贾伟康2 小时前
【HarmonyOS 7新能力|048】Taihe IPC工程封装:把接入逻辑放进可维护的分层结构
harmonyos·arkts·ipc·分布式通信·taihe
贾伟康2 小时前
【HarmonyOS 7新能力|045】LazyLayoutAlgorithm工程封装:把接入逻辑放进可维护的分层结构
性能优化·harmonyos·arkts·arkui·懒加载
梦想不只是梦与想12 小时前
鸿蒙 云测试:上架测试流程
harmonyos·鸿蒙·云测试
传奇开心果编程14 小时前
【ArkUI 练中学】第15课:UI 界面设计与实战
学习·ui·华为·harmonyos
HwJack2015 小时前
【HarmonyOS开发小实践】ArkUI 动画系统属性动画、显式动画与路径动画
ui·性能优化·harmonyos
李游Leo17 小时前
HarmonyOS 7 实战开发 05:把页面做到可上线状态
ios·harmonyos
贾伟康20 小时前
【HarmonyOS 7新能力|043】可变字体工程封装:把接入逻辑放进可维护的分层结构
harmonyos·arkts·arkui·ui设计·可变字体
HarmonyOS_SDK20 小时前
HarmonyOS智慧多窗,让应用在任意窗口都“恰到好处”
harmonyos