HarmonyOS 无障碍体验实战:朗读标签、焦点顺序与高对比模式
HarmonyOS 无障碍体验实战:朗读标签、焦点顺序与高对比模式
无障碍不是最后补几个标签。读屏用户能不能理解按钮含义,键盘或辅助设备能不能按正确顺序移动焦点,高对比模式下文字是否仍然可读,都会决定用户能否完成任务。本文用一个表单加列表的常见场景,拆解 HarmonyOS 应用里无障碍体验如何工程化。

一、无障碍先按任务路径验收
无障碍检查不能只看单个组件。要从用户任务出发,比如“搜索路线、打开详情、收藏路线、提交反馈”。
| 检查点 | 问题表现 | 验收方式 |
|---|---|---|
| 朗读标签 | 只读“按钮”,不知道用途 | 听读屏输出 |
| 焦点顺序 | 从底部跳到顶部 | 用键盘或辅助焦点走一遍 |
| 状态提示 | 收藏成功没有反馈 | 检查状态变更播报 |
| 对比度 | 高对比下按钮看不清 | 切换主题检查 |
| 动效 | 过度动画影响理解 | 提供减弱动效策略 |

二、资料与版本边界:本文写应用层无障碍落地
本文示例面向 HarmonyOS NEXT / ArkTS / ArkUI 工程,重点在应用层无障碍策略:朗读文案、焦点顺序、控件语义、状态提示、高对比配色和验收排查。具体组件属性和系统辅助能力以当前官方文档为准。

接入无障碍前先选一条真实任务路径
无障碍不能靠“组件都写了标签”来判断。读者落地时,建议先选一条用户真实任务路径,例如“搜索路线 -> 打开详情 -> 收藏 -> 返回列表”。这条路径跑通后,再扩展到登录、支付、反馈等页面。
| 路径节点 | 用户需要知道什么 | 页面要提供什么 |
|---|---|---|
| 搜索入口 | 输入框用途和当前内容 | 清晰 label 与 hint |
| 结果列表 | 有多少结果,当前卡片是什么 | 卡片语义和列表位置 |
| 详情页 | 关键距离、耗时、操作入口 | 结构化朗读内容 |
| 收藏按钮 | 当前是否已收藏 | 状态化标签 |
| 返回入口 | 返回到哪里 | 明确导航语义 |
这样写的好处是测试同学可以按任务路径验收,而不是在页面上随机点控件。用户真正关心的是能不能完成任务,不是某个控件有没有属性。
把颜色、动效和焦点都纳入同一个页面状态
无障碍不是单一属性。高对比、减少动效、焦点可见性经常一起影响体验,最好用一个页面策略对象集中描述。
export interface AccessibilityPagePolicy {
pageName: string;
highContrast: boolean;
reduceMotion: boolean;
visibleFocusRing: boolean;
minTouchTargetVp: number;
}
export function routeDetailAccessibilityPolicy(): AccessibilityPagePolicy {
return {
pageName: 'RouteDetailPage',
highContrast: true,
reduceMotion: true,
visibleFocusRing: true,
minTouchTargetVp: 44
};
}
这段策略对象不直接渲染 UI,但它让页面验收有了明确目标:触控目标不能太小,焦点必须可见,关键动效要能减弱,高对比模式下仍然看得清。
三、语义标签:读出来要像人话
按钮、图标、卡片都要有用户能理解的语义,而不是技术名。
export type AccessibleRole = 'button' | 'image' | 'tab' | 'input' | 'card';
export interface AccessibilityLabel {
role: AccessibleRole;
label: string;
hint: string;
}
export function buildRouteCardLabel(title: string, distanceKm: number, favorite: boolean): AccessibilityLabel {
const stateText = favorite ? '已收藏' : '未收藏';
return {
role: 'card',
label: `${title},距离 ${distanceKm.toFixed(1)} 公里,${stateText}`,
hint: '双击打开路线详情'
};
}
这段模型负责生成读屏语义。它不处理 UI 样式,只保证用户听到的信息能完成判断。
四、焦点顺序:按视觉和任务顺序走
焦点顺序要符合用户认知。标题、搜索框、筛选、结果列表、主操作,通常比布局代码顺序更重要。
export interface FocusNode {
id: string;
order: number;
enabled: boolean;
}
export function sortFocusableNodes(nodes: FocusNode[]): FocusNode[] {
return nodes
.filter(node => node.enabled)
.sort((a, b) => a.order - b.order);
}
export function focusOrderValid(nodes: FocusNode[]): boolean {
const sorted = sortFocusableNodes(nodes);
for (let index = 1; index < sorted.length; index += 1) {
if (sorted[index].order <= sorted[index - 1].order) {
return false;
}
}
return true;
}
真实页面里可以把 order 映射到组件焦点规则。重点是让焦点顺序可检查,而不是靠碰运气。
五、状态播报:操作成功和失败都要被听见
收藏、提交、删除、加载失败这类状态变化,需要给读屏用户明确反馈。
export type AnnounceLevel = 'polite' | 'assertive';
export interface AccessibilityAnnouncement {
text: string;
level: AnnounceLevel;
}
export function buildActionAnnouncement(action: 'favorite' | 'submit' | 'delete', success: boolean): AccessibilityAnnouncement {
if (success) {
return { text: `${action} 操作已完成`, level: 'polite' };
}
return { text: `${action} 操作失败,请稍后重试`, level: 'assertive' };
}
普通成功提示可以温和播报;影响任务继续的失败要更高优先级。这样用户不会只看到视觉 Toast,却听不到结果。
六、高对比模式:颜色不能是唯一信息
错误、成功、禁用状态不要只靠颜色表达。要同时有文本、图标或状态标签。
export interface AccessibleColorToken {
textColor: string;
backgroundColor: string;
borderColor: string;
stateText: string;
}
export function resolveAccessibleToken(state: 'normal' | 'error' | 'success'): AccessibleColorToken {
if (state === 'error') {
return { textColor: '#B00020', backgroundColor: '#FFF4F4', borderColor: '#B00020', stateText: '错误' };
}
if (state === 'success') {
return { textColor: '#006D3B', backgroundColor: '#F0FFF6', borderColor: '#006D3B', stateText: '成功' };
}
return { textColor: '#111111', backgroundColor: '#FFFFFF', borderColor: '#666666', stateText: '默认' };
}
颜色 token 同时提供状态文本,方便组件在必要时显示文字标识。
七、减弱动效:不是所有用户都适合强动画
强动画可能影响阅读和操作,尤其是页面切换、弹窗和加载动画。
export interface MotionPreference {
reduceMotion: boolean;
}
export function resolveAnimationDuration(preference: MotionPreference, defaultMs: number): number {
if (preference.reduceMotion) {
return Math.min(defaultMs, 80);
}
return defaultMs;
}
减弱动效不是取消体验,而是在不影响理解的前提下降低刺激和等待感。
八、无障碍问题排查表
| 无障碍体验表现 | 优先怀疑的能力缺口 | 排查方式 | 修复方向 |
|---|---|---|---|
| 读屏只读按钮 | 缺少语义标签 | 听读屏输出 | 补充 label 和 hint |
| 焦点乱跳 | 顺序和视觉不一致 | 走一遍焦点 | 设置明确 order |
| 操作成功没反馈 | 状态未播报 | 检查 announcement | 成功失败都播报 |
| 错误只靠红色 | 颜色是唯一信息 | 切高对比检查 | 增加文字状态 |
| 动效影响操作 | 没有减弱动效 | 打开辅助设置测试 | 缩短或关闭动画 |
| 图片读出文件名 | 图片没有可理解描述 | 检查 image label | 写业务含义 |
九、无障碍上线前验收表
| 无障碍验收点 | 通过结果 |
|---|---|
| 朗读标签 | 关键按钮、卡片、图片都有业务语义 |
| 焦点顺序 | 可按任务路径连续操作 |
| 状态反馈 | 成功、失败、加载都有可感知反馈 |
| 高对比 | 文字、按钮、边框仍可辨认 |
| 动效 | 可按用户偏好减弱 |
| 真机验证 | 至少完成一条核心任务读屏验收 |
无障碍验收最好由任务驱动。以“搜索路线并收藏”为例,用户应该能听懂搜索框用途、知道结果数量、按顺序进入路线卡片、完成收藏,并听到收藏成功反馈。如果中间任何一步需要靠视觉猜测,说明链路还没有真正走通。
失败复盘:录下读屏路径比截图更有用
无障碍问题经常不是截图能说明的。焦点跳跃、朗读顺序混乱、状态没有播报,都需要录屏或记录路径。可以把一次路径验收拆成节点,记录每一步听到的内容。
export interface AccessibilityStepRecord {
step: number;
focusId: string;
spokenText: string;
expectedText: string;
passed: boolean;
}
export function recordAccessibilityStep(
step: number,
focusId: string,
spokenText: string,
expectedText: string
): AccessibilityStepRecord {
return { step, focusId, spokenText, expectedText, passed: spokenText === expectedText };
}
这段记录用于验收和复盘。它不要求线上保留,而是帮助团队在回归阶段发现“视觉上没问题,但用户听不懂”的缺陷。
页面改造建议:先主操作,再补边角控件
第一步先找主任务。比如路线应用里,搜索、筛选、打开详情、收藏、开始导航就是主任务,不要一开始陷入每个装饰图标。
第二步改主操作标签。按钮要读出动作,卡片要读出标题、距离、状态,图片要说明是否传递信息。
第三步排焦点顺序。焦点要按用户完成任务的顺序走,而不是按代码写在哪一行走。尤其是浮层、底部按钮、弹窗关闭按钮,要人工走一遍。
第四步补状态反馈。收藏成功、提交失败、加载完成都要让用户感知到,不然用户会重复操作。
第五步看高对比和字体放大。颜色不能是唯一信息,文字变大后按钮不能被截断,焦点边框不能和背景融在一起。
不同角色可以怎么协作
| 角色 | 负责内容 | 交付物 |
|---|---|---|
| 产品 | 明确主任务路径和状态文案 | 路径说明和文案表 |
| 设计 | 提供高对比、焦点、字号方案 | 页面标注或设计稿 |
| 开发 | 落地语义、焦点、状态反馈 | 页面实现和策略对象 |
| 测试 | 录制读屏路径和失败点 | 录屏、问题单、回归记录 |
| 运营或客服 | 收集用户真实反馈 | 典型问题归档 |
无障碍做得好不好,不是某一个角色能独立决定的。文章里的代码只是落地方式,真正稳定的是任务路径、文案和验收一起闭环。
十、无障碍相关官方资料
- 华为开发者文档:无障碍开发
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/accessibility-development - 华为开发者文档:ArkUI 组件开发
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-ui-development - 华为开发者文档:应用设计指南
https://developer.huawei.com/consumer/cn/design/
十一、把无障碍纳入日常验收
无障碍体验要和普通功能一起验收。语义标签让用户听懂,焦点顺序让用户走通,状态播报让用户知道结果,高对比和减弱动效让体验覆盖更多人群。
团队落地时可以给每个核心页面保留一条“无障碍路径”:入口是什么,焦点经过哪些控件,用户听到哪些状态,失败时怎么返回。这个路径写清楚以后,新需求修改页面结构时,也能知道哪些焦点和朗读内容不能破坏。
还要注意一个细节:无障碍不是只服务读屏。高对比、字体放大、键盘焦点、减少动效都会影响不同用户。工程上最好把这些能力归到同一张页面验收表里,每次改核心页面都走一遍,而不是等问题反馈后再补标签。
如果团队没有专门角色负责,也可以把这条路径交给测试同学在回归阶段执行,并把录屏或问题点贴回需求单。
| 辅助体验问题 | 推荐实现方式 |
|---|---|
| 读屏读什么 | 业务语义,不是技术名 |
| 焦点怎么走 | 按任务顺序 |
| 状态怎么反馈 | 成功失败都可感知 |
| 颜色够不够 | 不能只靠颜色 |
| 动效怎么处理 | 支持减弱策略 |
更多推荐



所有评论(0)