ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

HarmonyOS 7 FlexDesk:Pointer键盘焦点导航与快捷键一致性

HarmonyOS 7 FlexDesk:Pointer键盘焦点导航与快捷键一致性 前四篇把 FlexDesk 的“屏幕和窗口”问题基本做稳了。01 解决窗口断点和 DynamicLayout02 让手机底栏与平板侧栏共享同一导航状态03 进入分屏和悬浮窗连续缩放04 再把折叠、展开、悬停三个物理形态接进同一份业务状态。到了 05窗口已经能适配但我把应用放到 PC / 2in1 上用了一会儿还是觉得不对。问题不是布局。而是交互语言还停留在“触屏 App”鼠标移到任务上没有反馈 右键什么也没有 Tab 键不知道焦点去哪 键盘用户每次都要拿鼠标点按钮 详情区 Esc 也关不掉 同一个 task_1042 用鼠标、键盘和触屏时反馈不一致。HarmonyOS 当前 ArkUI 已经提供onHover、onMouse、焦点控制、keyboardShortcut、onKeyEvent与bindContextMenu(..., ResponseType.RightClick)等能力。官方键鼠事件文档也明确说明外接鼠标和触控板可以触发onHover / onMouseTab 与方向键会参与焦点导航组件快捷键从 API 10 开始可用并且快捷键优先于普通onKeyEvent。所以 05 不再动窗口布局专门解决同一业务状态在触屏、鼠标和键盘输入下保持一致。本轮统一数据taskId: adapt_20261003_05 page: ProjectDetailPage.ets window: 920 × 760vp inputProfile: MOUSE_KEYBOARD selectedProjectId: pj_harmony_26 selectedTaskId: task_1042 draftChars: 128 cursorOffset: 96 hoverTargets: 6 hoverEvents: 14 focusableTargets: 12 focusMoves: 9 focusLost: 0 contextMenuOpens: 2 contextMenuActions: 3 rightClickTaskId: task_1042 shortcutBindings: 2 shortcutHits: 4 keyEventHits: 5 duplicateShortcutBlocked: 1 avgInputDispatchCost: 0.8ms p95InputDispatchCost: 1.5ms stateRetained: true status: DESKTOP_INPUT_READY一、PC 适配不是把触控按钮做大而是把“可发现性”补回来手机上用户看到一张任务卡通常会直接点。PC 上鼠标移过去时如果界面完全没变化用户很难判断这一行能不能点 哪里是可交互区域 右键有没有扩展动作。所以 FlexDesk 先从onHover开始。Hover 不承担业务动作只承担“这里可交互”的反馈。例如任务task_1042未 hover 普通背景 hover 轻微描边 背景提升 selected 保持选中边框Hover 和 Selected 不能混成一个状态。否则鼠标刚移开选中态也跟着消失。二、Hover 状态只属于视图不写进业务 Store第一段代码解决的是鼠标悬停可以改变视觉但不能改变 selectedTaskId。Componentstruct DesktopTaskRow{ProptaskId:stringPropselectedTaskId:stringStateprivatehovered:booleanfalsebuild(){Row(){Text(this.taskId)}.focusable(true).onHover((isHover:boolean){this.hoveredisHover}).backgroundColor(this.hovered?#F2F7FF:Color.Transparent).border({width:this.taskIdthis.selectedTaskId?2:0,color:#3977F6})}}本轮六个任务卡都支持 hoverhoverTargets6测试过程中累计hoverEvents14但selectedTaskId一直还是task_1042这就是视图反馈和业务选择的边界。三、右键菜单应该围绕当前任务不应该重新选一遍ArkUI 当前bindContextMenu支持ResponseType.RightClick。FlexDesk 对任务卡提供三个项目级动作打开任务 复制任务 ID 加入收藏右键task_1042时rightClickTaskIdtask_1042菜单不是一个独立的数据源。它消费的是当前 TaskRow 自己的 taskId。第二段代码解决的是右键动作必须和触发对象绑定菜单打开本身不改变 selectedIndex。BuilderTaskContextMenu(taskId:string){Column(){Text(打开任务).onClick((){this.openTask(taskId)})Text(复制任务 ID).onClick((){this.copyTaskId(taskId)})Text(加入收藏).onClick((){this.pinTask(taskId)})}.width(180)}TaskRow({taskId:task_1042}).bindContextMenu(this.TaskContextMenu(task_1042),ResponseType.RightClick)本轮contextMenuOpens2 contextMenuActions3说明菜单被打开两次三个动作都分别验证过。四、右键菜单不是系统文件右键扩展菜单这里要分清两个概念。FlexDesk 使用的是ArkUI 组件上的 bindContextMenu作用于应用内部任务卡。HarmonyOS 当前还提供 PC / 2in1 文件右键扩展菜单能力可以在桌面或文件管理器里注册应用菜单项。这两个不是一回事。05 只做应用内部任务交互不把文件系统右键能力混进来。五、焦点链必须能用 Tab 和方向键走通PC / 2in1 上键盘用户最基础的体验不是快捷键而是Tab Shift Tab 方向键 EnterArkUI 当前焦点系统支持focusable defaultFocus tabIndex focusBox requestFocus官方焦点文档也说明Tab 与方向键可以触发走焦前提是组件本身具备获焦能力。FlexDesk 当前页面有12 个可获焦目标包括侧栏 4 项 任务列表 5 项 详情编辑区 保存按钮 更多按钮本轮focusMoves9 focusLost0从导航进任务列表再进详情和工具栏没有掉到未知焦点。六、焦点视觉不能只靠浏览器式默认轮廓触控用户不需要一直看到焦点框。键盘用户却必须知道自己“现在在哪”。FlexDesk 让任务卡hover selected focus拥有不同但兼容的样式。例如hover 浅蓝背景 selected 蓝色边框 focus 系统 FocusBox / 高对比外框三个状态可以同时存在。不要为了“画面干净”把 focus 样式去掉。那样键盘用户会失去方向感。七、快捷键要避开系统保留组合HarmonyOS 当前keyboardShortcut支持字符 / FunctionKey ModifierKey[]同时官方文档列出了不允许覆盖的系统快捷键例如Ctrl C Ctrl A Ctrl V Ctrl X Ctrl Z Ctrl Y Ctrl Shift ZFlexDesk 因此不去抢这些组合。当前绑定Ctrl K 打开命令面板 Ctrl Shift P 快速切换项目这两条属于 FlexDesk 项目约定。八、快捷键只绑定“动作”不绑定页面复制逻辑第三段代码解决的是鼠标点击和快捷键最终调用同一个 Command。Componentstruct DesktopCommandBar{build(){Row(){Button(命令面板).onClick((){this.commands.openPalette()}).keyboardShortcut(k,[ModifierKey.CTRL],(){this.commands.openPalette()})Button(切换项目).onClick((){this.commands.quickProjectSwitch()}).keyboardShortcut(p,[ModifierKey.CTRL,ModifierKey.SHIFT],(){this.commands.quickProjectSwitch()})}}}这样鼠标点按钮和Ctrl K不会出现两套实现。本轮shortcutBindings2 shortcutHits4两个快捷键各做了重复验证。九、普通按键事件继续交给 onKeyEvent快捷键适合Ctrl K Ctrl Shift P但 Enter、方向键、Esc 这类上下文按键更适合走焦点链和onKeyEvent。官方键盘事件数据流里也明确keyboardShortcut 优先于普通 onKeyEvent所以 FlexDesk 不用一个巨大的根节点 onKeyEvent 抢所有按键。当前shortcut 处理全局命令 onKeyEvent 处理当前焦点组件语义。本轮记录keyEventHits5主要用于 Enter 确认、Esc 关闭详情等场景。十、文本编辑状态不能被快捷键误伤当前任务草稿128 chars cursor96如果 TextArea 正在输入CtrlC / CtrlV 等应该仍然属于系统和输入组件。FlexDesk 不绑定这些系统保留组合。而CtrlK命令面板触发以后draftChars128 cursorOffset96仍然保持。也就是说快捷键打开命令不应该把编辑器重新创建一次。十一、重复快捷键要防止 Command 重入用户按住某些按键时可能产生重复 key down。官方快捷键文档也说明快捷键在 value 键持续触发 down 时可能重复响应。FlexDesk 的 Command Dispatcher 增加简单重入保护同一个 command 执行中 → 不重复启动本轮duplicateShortcutBlocked1避免同一个项目切换面板瞬间弹出两层。十二、输入事件处理不能做耗时操作HarmonyOS 当前 API 26 还提供全局基础输入事件监听并明确提醒输入事件监听器在 UI 线程同步执行不应该做复杂计算或网络请求否则会导致卡顿。FlexDesk 05 即使主要使用组件级onHover / onMouse / onKeyEvent也遵守同一原则输入事件 → 只做本地判断 → 分发 command → 业务异步逻辑另走服务层本轮项目侧avgInputDispatchCost0.8ms p95InputDispatchCost1.5ms这是一组当前设备的工程基线不是系统固定性能。十三、同一个 task_1042 在四种交互里必须是同一个对象当前验证鼠标 hover task_1042 右键 task_1042 Tab 焦点到 task_1042 Enter 打开 task_1042 快捷键切回 Projects最终业务状态selectedProjectId pj_harmony_26 selectedTaskId task_1042 draftChars 128 cursorOffset 96没有变化。这就是stateRetainedtrue真正表达的事情。十四、DevEco 图里重点看“输入方式变了业务状态没变”开发图HiLogtaskId adapt_20261003_05 inputProfile MOUSE_KEYBOARD window 920x760vp hover task task_1042 hoverEvents 14 focusMoves 9 focusLost 0 contextMenuOpens 2 actions 3 shortcuts bound 2 hits 4 keyEvents 5 duplicateShortcutBlocked 1 state: pj_harmony_26 task_1042 draft128 cursor96 avgDispatch 0.8ms p95 1.5ms status DESKTOP_INPUT_READY整篇真正想做的是鼠标、键盘不是另一套业务只是另一组输入入口。十五、手机运行图为什么仍然展示 PC/2in1 调试数据最终运行图它是 FlexDesk 的诊断页不是假装手机变成 PC。页面展示Pointer Hover Right Click Menu Focus Chain Keyboard Shortcut State Continuity以及920×760vp MOUSE_KEYBOARD的本轮真实测试快照。用户最终看到的是一个明确结论DESKTOP_INPUT_READY十六、05 最后固定八组桌面输入测试第一组鼠标移入 / 移出任务卡Hover 正常。第二组右键 task_1042菜单对象正确。第三组Tab 焦点从侧栏走到任务列表。第四组方向键不会跳出可见焦点链。第五组CtrlK 打开命令面板。第六组CtrlShiftP 切换项目入口。第七组编辑草稿状态不被快捷键重建。第八组重复快捷键不会重复触发 Command。全部通过以后DESKTOP_INPUT_READY才成立。十七、下一篇只做最终多端回归FlexDesk 到现在已经覆盖手机窗口 平板侧栏 连续多窗口 浮窗 折叠屏 悬停态 PC / 2in1 鼠标 键盘与快捷键06 不再增加功能。最后固定五种 ProfilePHONE_TOUCH TABLET_TOUCH FLOATING_MOUSE FOLDABLE_HOVER PC_MOUSE_KEYBOARD各跑八轮。从窗口尺寸、导航、折叠、焦点、快捷键一直验收到监听器和定时器释放。到 06FlexDesk 系列正式收口。十八、鼠标悬停不应该把触摸设备也“染”成桌面状态onHover的存在不意味着页面永远处于桌面交互模式。FlexDesk 会把当前输入环境分成TOUCH MOUSE MOUSE_KEYBOARD真正显示 Hover 强调、右键提示和快捷键帮助时还要结合当前输入 Profile。原因很简单。同一个 2in1 设备可能接着鼠标办公 拔掉键盘以后直接触摸 再接回触控板。如果 UI 一旦出现过鼠标就永久展示Ctrl K 右键打开菜单触屏用户会看到很多自己当前用不到的提示。所以输入提示属于“当前交互上下文”不是设备永久属性。十九、右键菜单不能复制手机长按菜单的所有动作手机长按可以承载一些低频动作。PC 右键菜单则应该更接近桌面用户预期打开 复制 收藏 移动 删除但不能因为右键菜单空间大就把所有业务按钮都塞进去。FlexDesk 只保留和当前任务高度相关的局部动作。例如保存草稿 切换项目 打开命令面板属于全局工作流不应该出现在每张任务卡的右键菜单里。这会让右键菜单更稳定也避免以后任务能力越来越多时变成一张“第二工具栏”。二十、Context Menu 打开后焦点不能丢回页面根节点右键菜单出现时还有一个隐藏问题焦点链可能被临时打断。如果菜单关闭后焦点回到页面根节点键盘用户下一次按 Tab 会突然从页面最前面重新走一遍。FlexDesk 的策略是菜单打开前 记录 sourceTaskId / focus target 菜单关闭 优先把焦点恢复到触发菜单的任务项。所以右键task_1042后即使什么动作都不执行关闭菜单以后仍然能从task_1042继续 Tab 导航。这也是focusLost0比单纯“菜单能弹出”更值得记录的原因。二十一、焦点顺序应该跟视觉阅读顺序一致920vp 宽屏下页面同时有侧栏 任务列表 详情面板 顶部操作区如果组件树顺序和视觉布局顺序完全不同Tab 走焦会产生很强的跳跃感。FlexDesk 的目标顺序是侧栏导航 → 当前任务列表 → 当前详情 → 页面级操作而不是左上 → 右下 → 左中 → 顶部必要时使用tabIndex和 Focus Group 调整顺序。视觉布局可以因为窗口变化重新排布但焦点语义必须仍然符合用户对当前页面的阅读顺序。二十二、键盘快捷键要提供可见入口不能只靠“用户猜”快捷键最大的坑不是冲突而是没人知道。所以 FlexDesk 05 在 PC / 2in1 模式下会在命令面板和按钮 Tooltip 里展示Ctrl K 命令面板 Ctrl Shift P 快速切换项目如果用户只用鼠标也能在操作过程中自然发现快捷键。这种“可发现性”比 README 里列一页快捷键更有效。同时手机触摸模式不会一直展示这些提示避免干扰。二十三、快捷键命中以后还要保留当前编辑焦点用户在编辑 task_1042 的描述时按Ctrl K命令面板弹出。关闭以后理想状态是回到原 TextArea cursor96而不是页面根节点因此 FlexDesk 的命令面板记录previousFocusId退出时请求恢复焦点。这让快捷键成为“临时命令层”而不是把用户从编辑流程里彻底带走。二十四、右键和双击不能抢同一次鼠标序列任务行未来可能同时支持单击选中 双击打开 右键菜单如果 MouseEvent 处理不清楚很容易出现右键时先触发选中 双击时触发两次单击业务 菜单打开又触发详情切换。FlexDesk 把这些行为拆成Pointer feedback Selection command Open command Context command并通过事件类型和冒泡控制明确消费边界。输入设备越丰富越不能把所有逻辑都写进一个onMouse回调里。二十五、DESKTOP_INPUT_READY 的边界不是“PC 专用页面完成”最终状态并不表示 FlexDesk 新做了一套 PC 页面。它表达的是同一 ProjectDetailPage 在 920×760vp 下 除了保持前四篇的布局与状态连续之外 还具备 鼠标反馈 右键菜单 可见焦点 键盘走焦 自定义快捷键 重复命令保护 输入资源可释放也就是说桌面端能力是叠加到同一业务页面上而不是复制一个DesktopProjectDetailPage。这才符合整个 FlexDesk 系列“一套业务状态多种运行形态”的主线。参考资料Keyboard and Mouse Eventhttps://developer.huawei.com/consumer/en/doc/harmonyos-guides-V13/arkts-common-events-device-input-event-V13组件快捷键事件https://developer.huawei.com/consumer/cn/doc/harmonyos-references-v5/ts-universal-events-keyboardshortcut-V5焦点控制https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V14/ts-universal-attributes-focus-V14bindContextMenuhttps://developer.huawei.com/consumer/en/doc/harmonyos-references-V14/ts-universal-attributes-menu-V14全局基础输入事件监听https://developer.huawei.com/consumer/cn/doc/doccenter-capabilities/api/ts-inputeventmonitor
返回列表