鸿蒙 PC Markdown 编辑器桌面无障碍与焦点:键鼠、Slider 与 ArkWeb 焦点归还
鸿蒙 PC Markdown 编辑器桌面无障碍与焦点键鼠、Slider 与 ArkWeb 焦点归还PC Markdown 编辑器的无障碍不是给按钮补几个名称就结束。OhMarkdown 同时包含 ArkUI 活动栏、搜索输入、可调侧栏、设置分段控件和 ArkWeb CodeMirror键盘焦点会跨原生与 Web 两个运行时移动。命令执行后若焦点丢失用户不能继续输入语言按钮若只有颜色辅助技术不知道当前选项侧栏若只支持拖动键盘用户无法改变宽度隐藏文本若被裁切辅助功能树也会暴露不完整布局。本文基于公开仓库 https://gitcode.com/VON-/codex_md_oh 的已完成实现核心提交包括命令与焦点基线ad1e31a、语言无障碍状态ed13ee0、侧栏 Slider 与标签修复358eb3f、窄搜索完整性0d8d38b。文章只陈述已有代码与 MateBook Pro 2in1 模拟器证据不把尚未执行的全量屏幕阅读器真机审计写成通过。焦点是桌面工作流状态移动端常以触控命中为主PC 编辑器却要求连续键盘操作。用户在 CodeMirror 输入按CtrlP打开快速打开输入文件名方向键选择Enter 打开再继续输入或者按CtrlShiftP执行命令。每个步骤都必须明确焦点转移和归还。焦点错误有三种常见表现快捷键打开面板但输入框没有焦点用户文字仍写进文档执行命令后焦点停在隐藏面板编辑器无法输入ArkUI 重建布局时焦点被丢到窗口起点键盘用户需要重新 Tab 很远。因此焦点不应依赖“浏览器或系统大概会处理”。入口函数在面板切换后延迟请求具体 focus key结果打开后 Web 的jumpToOffset主动editor.focus()命令面板关闭也归还编辑器。活动栏图标必须有可读名称活动栏使用 SymbolGlyph不显示“文件、搜索、大纲”文字。视觉用户依赖熟悉图标辅助技术不能从图形猜用途所以 Builder 接收 Resource label 并设置accessibilityText。BuilderprivateactivityButton(icon:Resource,label:Resource,panel:string){Button(){SymbolGlyph(icon).fontSize(21).fontColor([this.activePanelpanelthis.sidebarOpen?#087A63:$r(app.color.workspace_text_secondary)])}.type(ButtonType.Normal).width(36).height(36).accessibilityText(label).onClick(()this.selectPanel(panel))}名称来自中英文资源语言切换后辅助功能文字同步。36 × 36 vp 命中区域稳定选中时背景和颜色改变但尺寸不变。当前 activePanel 与 sidebarOpen 的视觉选中状态还可进一步补accessibilitySelected现有语言分段按钮已经采用该模式。工具栏纯图标按钮也传入open/new/close/toggle sidebar等资源名称。使用标准 SymbolGlyph 而非手绘 SVG使视觉与平台语义保持一致但真正的朗读仍由 accessibilityText 明确提供。分段选择需要 selected 语义界面语言有跟随系统、简体中文、English 三项。背景色只能说明视觉状态辅助功能树必须知道哪个按钮选中。实现把applicationLanguage的比较结果同时用于背景和accessibilitySelected。Button(label).type(ButtonType.Normal).layoutWeight(1).height(28).backgroundColor(this.applicationLanguagelanguage?$r(app.color.workspace_sync_selected):Color.Transparent).accessibilitySelected(this.applicationLanguagelanguage).onClick(()this.updateApplicationLanguage(language))模拟器最终返回跟随系统 Button selectedtrue简体中文和 English 为 false。强制重启后结果不变既证明语义也证明持久化保存的是策略。自动保存、图片目录和拖放模式也是互斥分段控件当前视觉选中清晰但代码还没有为所有这些 Builder 都补齐accessibilitySelected。这是已知审计项不能因为语言控件通过就宣称整个设置面板已经完整无障碍。可调侧栏应当是 Slider侧栏分隔线没有文字也不像传统按钮其交互本质是有限范围数值调整。实现设置AccessibilityRoleType.SLIDER、资源化名称和当前 vp description并允许获得 Tab 焦点。.focusable(true).tabStop(true).accessibilityText($r(app.string.resize_sidebar)).accessibilityDescription(${Math.round(this.sidebarWidth)}vp).accessibilityRole(AccessibilityRoleType.SLIDER).onKeyEvent((event:KeyEvent):booleanthis.handleSidebarResizeKey(event))模拟器辅助功能树在重启后显示description392 vp。这让不可见的 Preferences 数值成为可感知状态。角色告诉辅助技术它是调整控件而不是装饰分隔线。当前平台代码没有提供标准化 min/max/value 属性只通过 description 报告当前值。后续应评估更完整的范围语义使屏幕阅读器可以朗读“392最小 220最大 480”。现有实现是可操作基线不是最终审计结论。方向键提供精确替代路径Slider 获得焦点后左右方向键以 16 vp 步长调整。只处理 Key Down 与两个方向键其他事件继续传播。每次更新通过动态窗口 clamp并持久化。privatehandleSidebarResizeKey(event:KeyEvent):boolean{if(event.type!KeyType.Down||(event.keyCode!KeyCode.KEYCODE_DPAD_LEFTevent.keyCode!KeyCode.KEYCODE_DPAD_RIGHT)){returnfalse;}constdeltaevent.keyCodeKeyCode.KEYCODE_DPAD_LEFT?-16:16;this.sidebarWidththis.clampSidebarWidth(this.sidebarWidthdelta);this.persistSidebarWidth();returntrue;}键盘路径不只是无障碍备用也适合精确微调。鼠标拖到大致宽度再用方向键调整 16 vp比尝试停在特定像素更可控。边界 220/480 由同一 clamp 保护不会因为输入方式不同得到越界状态。当前尚未支持 Home/End 直接到最小/最大也没有双击恢复默认。它们可以作为后续效率功能但不能替代已存在的基本方向键操作。搜索输入的焦点请求打开搜索面板或切换搜索模式后WorkspaceShell 使用稳定 focus keysearch-query-input请求焦点。延迟 60 或 100 ms 是为了等待条件 Builder 完成布局如果在状态切换同一同步栈立即请求目标可能尚未挂载。privatesetSearchPanelMode(mode:SearchPanelMode):void{this.searchPanelModemode;if(modeSearchPanelMode.QUICK_OPENthis.workspaceRootUri.length0){this.executeWorkspaceSearch();}setTimeout((){focusControl.requestFocus(search-query-input);},60);}Quick Open 允许空查询并立即加载候选输入框仍获得焦点用户可直接键入。Current/Workspace 切换也复用同一 focus key不因 placeholder 变化创建新的键盘路径。定时请求是实用方案但固定 60 ms 不是强同步保证。低性能真机或复杂动画下仍需验证更理想是组件挂载回调或明确的下一帧机制。当前 MateBook Pro 2in1 模拟器纯键盘CtrlP - plan - Enter已通过。搜索列表的键盘导航输入框处理非 Current 模式的方向键、Enter 与 Escape。上下键更新选中索引并让 Scroller 滚动Enter 打开当前项搜索运行中 Escape 取消。没有结果时不消费方向键保留输入控件默认行为。if(event.keyCodeKeyCode.KEYCODE_DPAD_DOWN||event.keyCodeKeyCode.KEYCODE_DPAD_UP){constdeltaevent.keyCodeKeyCode.KEYCODE_DPAD_DOWN?1:-1;constnextIndexMath.max(0,Math.min(this.workspaceSearchResults.length-1,this.workspaceSearchSelectedIndexdelta));this.workspaceSearchSelectedIndexnextIndex;this.workspaceSearchScroller.scrollToIndex(nextIndex,true);returntrue;}选中索引始终钳制不会越界。列表滚动与选中同步键盘用户不需要猜当前项。结果行稳定高度和路径省略避免选中背景改变布局。搜索条件切换会清理旧结果避免键盘 Enter 打开按旧 Regex 条件生成的候选。布局从两行切单行不会改变索引或条件它只是视觉变化。跨 ArkUI 与 ArkWeb 的快捷键路由CodeMirror 处于焦点时Web 监听CtrlP和CtrlShiftP。前者向原生发quickOpen后者在 Web 内打开命令面板。修饰键分支明确避免两者同时触发。if(keypevent.shiftKey){event.preventDefault();commandPalette.hidden?openCommandPalette():closeCommandPalette();return;}if(keyp!event.shiftKey){event.preventDefault();window.OhMarkdownEditor?.requestCommand(quickOpen);return;}Web 只发送受限命令名原生负责打开侧栏和聚焦输入。文件枚举权限不进入 ArkWeb。Meta 兼容保留但鸿蒙 PC 主路径用 Control 验证。快捷键命令 ID不随语言变化。中文命令面板可以用“保存”搜索但执行仍是file.save焦点路由基于稳定 ID不依赖翻译文本。精确跳转后归还编辑器焦点工作区搜索结果打开后原生读取最新文件、解析偏移、切到源码模式再调用 WebjumpToOffset。Web 设置 selection、滚动到可见位置最后editor.focus()。functionjumpToOffset(offset:number,length:number0):boolean{if(!Number.isInteger(offset)||!Number.isInteger(length)||offset0||length0||offsetlengtheditor.state.doc.length){returnfalse;}if(currentModepreview){setMode(source);}editor.dispatch({selection:{anchor:offset,head:offsetlength},effects:EditorView.scrollIntoView(offset,{y:start,yMargin:18})});editor.focus();returntrue;}用户按 Enter 打开结果后可以立即输入或用键盘扩展选择不需要再点击编辑区。函数对非法偏移返回 false原生把它视为失败不假装焦点已正确落位。预览模式下先切源码避免在不可编辑 DOM 中设置 CodeMirror 选择。焦点和视图模式作为跳转语义的一部分保证结果可见且可继续操作。命令面板关闭后的焦点连续性命令面板是 Web 内部 overlay。打开时查询输入获得焦点方向键在候选间移动Enter 执行Escape 关闭。关闭后应把焦点还给 EditorView否则用户下一次按键可能落到 body 或隐藏 input。命令执行函数与面板状态分开disabled 命令不能执行原生命令通过受限 Bridge纯 Web 命令在 EditorView 上操作。无论哪条路径面板关闭不重建编辑器。Playwright 命令面板测试覆盖打开、筛选、键盘执行和 Bridge mock。运行时语言切换测试还证明中文关键词更新后面板继续可操作。真实设备命令截图展示筛选与执行同步但完整屏幕阅读器朗读顺序仍需真机专项审计。本地化必须同步 ARIAArkWebsetLocale不只更改可见文本还更新documentElement.lang、workspace、editorHost、preview、commandPalette、查询和候选列表 aria-label。三方差异的标题、图例、栏名和关闭按钮也同步。document.documentElement.langeditorLocale;workspace.setAttribute(aria-label,messages.workspaceLabel);editorHost.setAttribute(aria-label,messages.sourceEditorLabel);preview.setAttribute(aria-label,messages.previewLabel);commandPalette.setAttribute(aria-label,messages.commandPaletteLabel);commandQuery.setAttribute(aria-label,messages.searchCommands);如果只改变视觉文案屏幕阅读器可能仍以英文语言规则朗读中文。lang 与 aria 同步让两套 UI 栈在切换后保持一致。CodeMirror 不重建焦点和 selection 保留。中文系统跟随模式重启后原生辅助功能树显示中文并保留 selected英文模式则显示英文原生与 Web 占位。这是本地化和无障碍交叉验证而不是两个互不相关功能。窄侧栏中文本完整也是无障碍问题220 vp 侧栏中旧布局裁切“正则表达式”。修复后辅助功能树给出三个完整文本边界区分大小写[706,627][811,651]全词匹配[926,627][1010,651]正则表达式[706,680][811,704]。界面截图能看出两行辅助树边界进一步确认文本节点没有落到容器外。扩大到 408 vp 后三者纵坐标相同恢复单行。状态与标签不因布局分支丢失。无障碍测试因此也是响应式布局测试。文字被视觉裁切但 accessibilityText 仍完整并不代表可接受因为低视力用户仍依赖视觉反过来视觉完整但节点无名称也不合格。两条证据都需要。真实应用截图下面截图来自 HarmonyOS MateBook Pro 2in1 模拟器。侧栏调整柄位于文件面板与编辑区之间可获得 392 vp description工作台中活动栏、标签、模式按钮和状态栏保持稳定。设备还验证纯键盘快速打开编辑器中CtrlP输入plan方向或默认选中后 Enter目标docs/plan.md打开且编辑器获得焦点。命令面板和搜索准确跳转各有真实应用截图支持功能结果。截图不能展示焦点朗读内容辅助功能树和自动化补足这部分。当前没有录制完整屏幕阅读器语音因此不宣称 WCAG 或某等级认证只记录已实现语义与剩余审计项。自动化与设备验证分层Playwright30/30覆盖命令面板键盘、快捷键路由、运行时语言、搜索跳转和 Web 焦点相关行为。ArkTSUnitTestBuild覆盖语言与侧栏解析。Debug HAP、ohosTest HAP 构建通过MateBook Pro 2in1 模拟器 ohosTest7/7。最终 Debug HAP SHA-256 为367ab8650479aa1fa8fe73bd1ebadd9a53f46659c850c2e388fc799d5cb88e5bohosTest HAP 为b7230037b51044fe16168d2c835fb891e1c70f675941a1046165bc895217592c。两者未签名。Web 自动化擅长精确断言 activeElement、selection 和 aria模拟器擅长真实 ArkUI 焦点、辅助树和键盘事件真机还需要验证物理键盘、触控板、屏幕阅读器和显示缩放。三者不能互相冒充。已知缺口与审计清单自动保存和图片分段按钮还应统一补 selected 语义活动栏可补当前面板 selected/expanded文档标签应朗读文件名、活动状态和是否已修改侧栏 Slider 可补 min/max/value搜索项整行点击与 checked 朗读需要专项验证。跨 300 vp 断点时 Checkbox 焦点是否保持尚未记录虽然拖动时焦点通常在调整柄。系统大字体、RTL、高对比度、仅键盘关闭冲突弹窗、焦点陷阱和屏幕阅读器完整顺序都应进入后续真机矩阵。这些缺口不否定现有能力但决定了报告用词可以说关键路径具备名称、selected、Slider、方向键和焦点归还不能说整个应用已经完成全面无障碍认证。结论OhMarkdown 已把焦点与无障碍作为鸿蒙 PC 工作流状态处理图标按钮有资源化名称语言选择暴露 selected侧栏以 Slider 角色进入 Tab 顺序并支持方向键搜索模式主动聚焦输入结果跳转和命令关闭归还 CodeMirrorArkWeb 切换语言同步 lang 与 ARIA。真实模拟器辅助树证明跟随系统选中、392 vp Slider 和窄侧栏完整文本纯键盘快速打开与自动化继续通过。下一步不是宣布审计完成而是沿现有模式补齐所有分段控件、标签脏状态、标准范围值和真机屏幕阅读器矩阵让 PC 高效路径与无障碍路径真正使用同一套稳定交互。

相关新闻

开源项目盈利模式与开发者生存指南

开源项目盈利模式与开发者生存指南

1. 开源开发者的生存现状在代码开源的世界里,有一个令人尴尬的悖论:最受欢迎的开源项目往往由最贫穷的开发者维护。我认识一位维护着下载量过亿的npm包的开发者,他每天下班后要花4小时处理issue,周末还要写新功能,而这…

2026/7/21 2:24:14阅读更多 →
鸿蒙 PC Markdown 编辑器状态一致性:脏标记、修订号与保存基线

鸿蒙 PC Markdown 编辑器状态一致性:脏标记、修订号与保存基线

鸿蒙 PC Markdown 编辑器状态一致性:脏标记、修订号与保存基线 编辑器状态不是一个 isDirty布尔值。正文可能等于打开基线、恢复基线或保存请求时快照;保存期间还可以继续输入;多标签各有 URI、格式、revision和撤销历史;ArkUI与…

2026/7/21 2:24:14阅读更多 →
科学减腹:代谢调节与生活习惯优化指南

科学减腹:代谢调节与生活习惯优化指南

1. 项目概述:健康减腹的核心逻辑很多人误以为缩小腰围必须通过极端节食或高强度训练才能实现,实际上腹部脂肪堆积的本质是代谢失衡和生活方式紊乱的综合结果。我在营养咨询领域工作八年,处理过数百例腹部肥胖案例,发现真正有效的减…

2026/7/22 2:51:57阅读更多 →
《奇迹mu荣耀出征》|官方指南 1.03H原汁原味怀旧服

《奇迹mu荣耀出征》|官方指南 1.03H原汁原味怀旧服

游戏简介|正版1.03H复古奇迹 纯净无魔改 《荣耀出征》又名《奇迹MU1.03H复古荣耀服》《罗兰百人攻城怀旧奇迹》,是由安徽游昕联合忆往游戏正版运营的复古魔幻MMORPG怀旧手游。游戏严格复刻经典端游1.03H原版全部内容,无数值魔改、无浮夸特效…

2026/7/22 4:46:33阅读更多 →
基于ResNet的胸部X光影像识别系统开发实践

基于ResNet的胸部X光影像识别系统开发实践

1. 项目概述胸部X光影像识别一直是医疗AI领域的热门研究方向。作为一名长期从事医学影像分析的从业者,我最近完成了一个基于ResNet算法的胸部X光影像识别系统,这个项目整合了带标签数据集、模型训练权重以及基于PyQt5的可视化界面,为医生和研…

2026/7/22 4:46:33阅读更多 →
上海工业一站式涂装服务商:上海善屹涂装,多工艺复合喷涂解决高端制造表面处理痛点

上海工业一站式涂装服务商:上海善屹涂装,多工艺复合喷涂解决高端制造表面处理痛点

一、上海本地涂装市场现状:制造企业选择喷涂加工厂的核心痛点2026 年长三角高端制造产业持续扩容,新能源汽车、精密医疗设备、户外工程机械、不锈钢泵阀金属构件出货量逐年上涨,金属表面涂装不再只是简单上色,而是决定产品使用寿命…

2026/7/22 4:46:33阅读更多 →
03-协议基础02:USB架构与设备交互

03-协议基础02:USB架构与设备交互

文章目录 概述 一、USB拓扑结构回顾 1.1 Root Hub与External Hub 二、USB设备状态迁移 2.1 状态机 2.2 状态详解 2.3 从连接到可用 三、USB设备硬件识别 3.1 速度分类 3.2 全速设备识别 3.3 低速设备识别 3.4 高速设备识别(Chirp协商) 3.5 高速协商三种情况 四、USB3.0设备识别…

2026/7/22 4:46:33阅读更多 →
Docker快速入门:30分钟掌握容器化部署

Docker快速入门:30分钟掌握容器化部署

1. Docker 快速入门实操指南 作为一名在容器化领域摸爬滚打多年的老手,我经常被问到"如何快速上手Docker"。今天就用最直白的方式,带你在30分钟内完成从安装到运行第一个容器的完整流程。不同于官方文档的学院派风格,这里只讲真正…

2026/7/22 4:46:31阅读更多 →
告别数据孤岛与AI“水土不服”:金仓多模融合时序库如何让数据真正服务于业务

告别数据孤岛与AI“水土不服”:金仓多模融合时序库如何让数据真正服务于业务

当AI走进工业、能源等真实业务场景,常常会“水土不服”。一个简单的设备异常判断,AI需要的不仅是当下的读数,更需要理解设备过去的状态变化、关联设备的同步信息,甚至要结合维修记录和故障知识库。这些分散在不同系统中的数据&…

2026/7/22 4:44:31阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →