ArkUI + HarmonyOS 待办清单:无障碍语义与大字布局评审【共创稿事节】
一个待办事项在视觉上看起来非常简单:左侧一行标题,右侧一个“完成”按钮,下面再放一行说明。可把屏幕阅读功能打开以后,用户听到的可能是“按钮、按钮、文本”,却听不出来哪个按钮对应哪条任务。再把系统字体调大,标题挤成三行,按钮被挤出屏幕;页面原本展示得越紧凑,问题反而越容易暴露。设计一个看起来整洁的列表,跟设计一个可以被不同用户稳定操作的列表,是两项需要分别核查的工作。
这次选择一个完全独立的 HarmonyOS 待办清单页面,不需要前面任何连载项目,也不依赖三方库。评审目标包括三件事:每条内容能被完整理解、每个操作能被明确识别、文字变大以后交互仍然可达。代码以 ArkUI 的普通组件属性为主,避免把系统 Accessibility Kit 服务侧接口误当成页面必须调用的权限能力。

从视觉信息结构反推朗读结构
先明确产品中的最小语义单位。这里每条待办包含稳定 id、title、detail 和 completed 四项,用户可执行的动作是“标记完成”或“撤销完成”。标题和描述是静态内容,右侧按钮是独立交互对象。视觉上可以用卡片把二者放在一起,但无障碍焦点不应把整个卡片当成一个大按钮,因为这样会让用户无法准确区分“正在朗读信息”和“准备执行动作”。
推荐的阅读路径是:先听到任务标题及说明,然后移动焦点到与该任务绑定的操作按钮。按钮的朗读内容应包含任务名和动作含义,而不是只说“完成”。例如“标记完成:检查备份文件”,要比相邻多个按钮都叫“完成”更容易操作。若按钮执行后状态改变,文案要跟着切换成“撤销完成:检查备份文件”,避免视觉已经更新、辅助技术仍读出旧动作。必要时再补充 accessibilityDescription 告知操作后果,而不是把每个状态细节都挤进屏幕上的按钮标题。
对纯装饰性的分隔线和重复图形,原则相反:不承载信息,就不要制造一个多余焦点。官方屏幕朗读适配指南说明,accessibilityGroup(true) 可以把静态子内容归为一个整体,accessibilityLevel('no') 可以让无需被识别的装饰对象不进入朗读导航。但含独立按钮的整个行容器不能盲目设置为一个朗读组:组件被合并后,内部控件可能不再分别获得无障碍焦点。

先让一个列表项读得准确,再让列表跑起来
下面提供一个可以直接放在 Stage 模型 entry 模块 src/main/ets/pages/Index.ets 中的简化页面。它只依赖 ArkUI 标准组件,不访问网络、相册、位置或其他受限资源,因此无需额外声明危险权限。列表状态在页面内保存;如果产品需要跨启动持久化,可以另行接入存储服务,但那不属于无障碍属性的职责范围。
interface TodoItem {
id: string;
title: string;
detail: string;
completed: boolean;
}
@Entry
@Component
struct Index {
@State items: TodoItem[] = [
{ id: 'backup', title: '检查备份文件',
detail: '确认昨天的归档文件可以正常打开', completed: false },
{ id: 'review', title: '复核上线清单',
detail: '核对依赖版本、权限与发布说明', completed: true },
{ id: 'notice', title: '发送项目提醒',
detail: '告知协作成员本周的交付安排', completed: false }
];
private toggle(id: string): void {
this.items = this.items.map((item: TodoItem) => {
if (item.id !== id) return item;
return { id: item.id, title: item.title,
detail: item.detail, completed: !item.completed };
});
}
build() {
Column({ space: 12 }) {
Text('今日待办')
.fontSize(26)
.fontWeight(FontWeight.Bold)
.width('100%')
Scroll() {
Column({ space: 12 }) {
ForEach(this.items, (item: TodoItem) => {
Row({ space: 12 }) {
Column({ space: 6 }) {
Text(item.title)
.fontSize(18)
.fontWeight(FontWeight.Medium)
.width('100%')
Text(item.detail)
.fontSize(15)
.fontColor('#4A5568')
.width('100%')
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.accessibilityGroup(true)
.accessibilityText(item.title + '。' + item.detail)
Button(item.completed ? '撤销' : '完成')
.onClick(() => this.toggle(item.id))
.accessibilityText(
(item.completed ? '撤销完成:' : '标记完成:') + item.title
)
.accessibilityDescription(
item.completed ? '将这项任务改为未完成' : '将这项任务改为已完成'
)
}
.width('100%')
.padding(14)
.borderRadius(12)
.backgroundColor('#F5F8FC')
}, (item: TodoItem) => item.id)
}
.width('100%')
}
.layoutWeight(1)
}
.padding(18)
.width('100%')
.height('100%')
}
}
ForEach 使用稳定的业务 id 作为键,而不是数组下标。这样当未来增加排序和筛选时,条目身份不会因索引变化而混淆。toggle() 创建新数组并重新赋值,方便 ArkUI 感知列表状态变化。此处没有把“完成”状态只画成绿色对勾;操作文案本身会根据状态同步变化,即使用户看不到颜色,也能知道下一次点击的含义。
代码最值得注意的不是某个复杂 API,而是分组范围。只把左侧标题和说明放进 Column 的朗读组;右侧 Button 保留独立操作焦点。为了避免同一个信息被重复播报,组的 accessibilityText 提供一次完整的摘要,按钮则用带任务名称的动词短句表达动作。实际屏幕阅读顺序受布局和系统行为影响,仍需在目标设备上核查,不应仅凭代码顺序推断真实朗读效果。
大字体不是把 16 改成 20 就算适配
设计评审常把文字放大当成“字号提升”,但真正需要关注的是布局约束。假设任务说明由一行扩为三行,左侧 Column 是否还能自然增高?右侧操作按钮是否被压缩得无法点中?整个页面是否具备纵向滚动?这些问题不能靠给每个 Text 一个固定高度解决。相反,固定高度和过度使用省略号往往会隐藏重要信息。
本示例使用 Scroll 承载纵向内容,列表卡片不固定高度,文本区域通过 .layoutWeight(1) 占据可用宽度。这是保持内容伸展能力的基本结构,而非承诺所有极端字体倍率都能自动适配。尤其在非常窄的窗口中,标题和按钮可能相互争夺宽度,此时应考虑把操作按钮移到卡片下一行。不要仅依靠自动缩小字号,因为“内容完整”和“操作易达”通常比保持单行排版更重要。
可以用一个独立的布局决策函数把分支写清楚,再让组件按结果安排横向或纵向容器。这是项目自身的纯函数,不涉及未开放的系统设备识别接口:
export type CardArrangement = 'horizontal' | 'vertical';
export function chooseArrangement(
availableWidthVp: number,
requiresLargeText: boolean
): CardArrangement {
if (requiresLargeText || availableWidthVp < 360) {
return 'vertical';
}
return 'horizontal';
}
这里的 360vp 是当前示例的设计阈值,不是 HarmonyOS 平台规定的通用断点。requiresLargeText 也应由应用已验证的字体适配策略确定,不能随意根据手机型号猜测。将其接入实际布局时,可用父容器宽度或布局约束选择 Row 与 Column,并在大字体模式下让“完成”按钮单独占据下一行。更重要的是重新检查焦点走向:排列方向变了之后,语义阅读仍应先接收任务信息,再到操作按钮。

用可核对的路径完成无障碍验收
适配结果不该只由设计师看一眼截图决定。首先使用系统屏幕阅读功能从页面标题进入第一条任务,按正常手势依次移动焦点,记录是否完整读出标题、说明和动作。然后点击第二条任务的“撤销”,继续移动焦点,确认动作文案反映变化。接下来把系统文本显示调大,检查三条卡片是否能完整滚动、按钮是否可见且可操作,尤其注意长说明和窄窗口。最后使用键盘或其他可用输入方式确认焦点导航顺序合理,不能出现不可见但仍被选中的控件。
这套验收至少要覆盖四类问题。内容问题:是否漏读了状态、单位或行动对象;操作问题:同名按钮能否区分;布局问题:文字放大后是否遮挡或裁切;焦点问题:装饰对象有没有抢占焦点、可交互对象有没有被错误合并。每个问题应记录操作步骤、预期朗读内容、实际观察与修复位置。若发现用户需要重复听到相同说明才能找到按钮,应优先优化语义组织,而不是把朗读文本写得越来越长。
无障碍不是给页面最后加一个属性就结束。对这个待办清单来说,它首先是一项信息架构设计:哪些元素有意义、哪些是操作、哪些应被合并,决定了信息能不能有效传达;其次才是屏幕宽度、字号和焦点路径的工程落地。把静态语义与交互动作分开,让内容可以自然换行、让状态变化具备可朗读文案,再在真实设备上走完操作路径,比只看正常字号下的漂亮截图更接近可交付的质量标准。
官方资料:应用适配屏幕朗读、焦点控制、Accessibility Kit 概述。
更多推荐

所有评论(0)