HarmonyOS7 无障碍适配:5 个改动让你的 App 对所有人都友好
文章目录
前言
说实话,我之前写代码从来不考虑无障碍——觉得那是"加分项",不是必选项。直到有天看到一个视障朋友用读屏软件操作手机,那个体验让我破防了。一个没有语义化标签的按钮,读屏软件只能读出"未命名按钮"——你让人家怎么用?
无障碍不是锦上添花,是基本的尊重。

好消息是,HarmonyOS7 的无障碍适配门槛很低,5 个改动就能覆盖大部分场景。今天逐个讲清楚。
无障碍(Accessibility)的目标很简单:让所有人都能用你的 App。不只是视障用户,还有老年人、手部不便的用户、甚至在强光下看不清屏幕的普通人。
你以为无障碍是少数人的需求?全球有超过 10 亿残障人士,中国超过 8500 万。而且很多应用商店(包括 AppGallery)已经开始把无障碍作为审核指标了。
不做无障碍,迟早要补课。
为什么要做无障碍
不只是道德层面,还有实际利益:
- 用户覆盖 —— 不做无障碍 = 直接放弃大量潜在用户
- 应用审核 —— 部分应用商店已把无障碍纳入评分
- 代码质量 —— 语义化标签让代码更清晰,方便维护
- SEO 类比 —— 就像网页做 SEO 一样,做好无障碍 = 做好"应用优化"
无障碍能力概览
HarmonyOS7 提供的无障碍能力一览:
| 能力 | 属性/方法 | 说明 |
|---|

| 语义化文本 | accessibilityText | 给组件添加读屏文本 |
| 语义化提示 | accessibilityHint | 提示操作结果,如"点击后打开设置" |
| 焦点管理 | accessibilityNextFocusId | 控制焦点移动顺序 |
| 组件角色 | accessibilityRole | 标记组件类型(按钮/链接/标题等) |
| 朗读支持 | accessibilityLevel | 控制组件是否可被朗读 |
| 触摸目标 | hitTestBehavior / responseRegion | 扩大可点击区域 |
| 高对比度 | colorMode | 适配高对比度模式 |
| 分组 | accessibilityGroup | 将多个组件作为整体朗读 |
改动 1:语义化标签(accessibilityText)
这是最重要、最优先要做的一件事。
没加 accessibilityText 的图标按钮,读屏软件只能读"按钮"——用户根本不知道这个按钮是干嘛的。
@Entry
@Component
struct AccessibilityTextDemo {
build() {
Row({ space: 16 }) {
Image($r('app.media.icon_search'))
.width(24)
.height(24)
.fillColor('#333333')
.accessibilityText('搜索')
.accessibilityHint('点击打开搜索页面')
Image($r('app.media.icon_settings'))
.width(24)
.height(24)
.fillColor('#333333')
.accessibilityText('设置')
.accessibilityHint('点击打开设置页面')
Image($r('app.media.icon_notification'))
.width(24)
.height(24)
.fillColor('#333333')
.accessibilityText('通知')
.accessibilityHint('点击查看通知消息')
}
.padding(16)
}
}

关键代码讲解:
accessibilityText('搜索')—— 读屏时会朗读"搜索",而不是"图片"或"未命名"accessibilityHint('点击打开搜索页面')—— 提示操作结果,用户知道点了会发生什么- 所有纯图标按钮必须加,这是最低要求
原则:如果一个组件去掉视觉样式后你不知道它是啥,就必须加
accessibilityText。
改动 2:焦点管理
默认的焦点移动顺序是按布局从上到下、从左到右。但有些场景需要自定义顺序——比如表单里"密码"输完后应该跳到"确认密码",而不是跑到旁边的广告位。
@Entry
@Component
struct FocusOrderDemo {
build() {
Column({ space: 12 }) {
TextInput({ placeholder: '用户名' })
.width('100%')
.height(48)
.id('input_username')
.accessibilityNextFocusId('input_password')
TextInput({ placeholder: '密码' })
.width('100%')
.height(48)
.id('input_password')
.type(InputType.Password)
.accessibilityNextFocusId('input_confirm')
TextInput({ placeholder: '确认密码' })
.width('100%')
.height(48)
.id('input_confirm')
.type(InputType.Password)
.accessibilityNextFocusId('btn_register')
Button('注册')
.width('100%')
.height(48)
.id('btn_register')
}
.padding(24)
}
}
关键代码讲解:
.id('input_username')—— 给组件设 ID,焦点管理要用accessibilityNextFocusId('input_password')—— 指定下一个焦点跳转目标,从用户名直接跳到密码- 这样焦点顺序就是:用户名 → 密码 → 确认密码 → 注册按钮,不会跳到不该跳的地方
改动 3:朗读支持
有些装饰性元素(分割线、背景图、间距)不需要被朗读,有些关键信息又容易漏掉。用 accessibilityLevel 和 accessibilityGroup 来控制:
@Entry
@Component
struct ReadLevelDemo {
build() {
Scroll() {
Column({ space: 16 }) {
Text('今日推荐')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.accessibilityLevel('yes')
.accessibilityRole('HEADER')
Row() {
Image($r('app.media.icon_decoration'))
.width(40)
.height(40)
.accessibilityLevel('no')
}
Row() {
Image($r('app.media.icon_avatar'))
.width(36)
.height(36)
.accessibilityText('用户头像')
Column() {
Text('张三')
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text('3 分钟前发布')
.fontSize(12)
.fontColor('#999')
}
.margin({ left: 8 })
.accessibilityGroup(true)
.accessibilityText('张三,3分钟前发布')
}
.padding(12)
.backgroundColor('#f5f5f5')
.borderRadius(8)
}
.padding(16)
}
}
}
关键代码讲解:
accessibilityLevel('yes')—— 明确可被朗读(默认就是 yes,显式写出来更清晰)accessibilityLevel('no')—— 不可朗读,装饰性图片用这个,读屏会跳过accessibilityGroup(true)—— 把子组件合并为整体朗读,不会分别读"张三"和"3分钟前发布",而是一次性读"张三,3分钟前发布"accessibilityRole('HEADER')—— 标记这是标题,读屏软件会额外提示"标题级别"
改动 4:高对比度适配
部分用户会开启系统的高对比度模式,如果你的 App 用了浅灰色文字(#999999)配白色背景,高对比度模式下可能直接看不见。
@Entry
@Component
struct HighContrastDemo {
@StorageLink('isHighContrast') isHighContrast: boolean = false
build() {
Column({ space: 12 }) {
Text('普通模式下的提示文字')
.fontSize(14)
.fontColor(this.isHighContrast ? '#000000' : '#999999')
Divider()
.color(this.isHighContrast ? '#000000' : '#e0e0e0')
.strokeWidth(this.isHighContrast ? 2 : 1)
Button('确认操作')
.width('100%')
.height(48)
.backgroundColor('#007DFF')
.fontColor(Color.White)
}
.padding(24)
}
}
关键代码讲解:
@StorageLink('isHighContrast')—— 监听系统高对比度状态变化fontColor(this.isHighContrast ? '#000000' : '#999999')—— 高对比度模式用纯黑,普通模式用灰色- 按钮颜色不用改,蓝底白字本身对比度就够
实际项目中,可以用资源限定词目录(
resources/high_contrast/)自动适配,不用手动判断。
改动 5:触摸目标扩大
小图标是触屏的噩梦——看得见点不着。HarmonyOS7 规范建议触摸目标最小 44x44vp,但很多图标只有 24x24vp。用 responseRegion 扩大点击区域:
@Entry
@Component
struct TouchTargetDemo {
build() {
Row({ space: 24 }) {
Image($r('app.media.icon_back'))
.width(24)
.height(24)
.fillColor('#333333')
.accessibilityText('返回')
.responseRegion({ x: -10, y: -10, width: 44, height: 44 })
.onClick(() => {
console.info('返回被点击')
})
Image($r('app.media.icon_close'))
.width(24)
.height(24)
.fillColor('#333333')
.accessibilityText('关闭')
.responseRegion({ x: -10, y: -10, width: 44, height: 44 })
.onClick(() => {
console.info('关闭被点击')
})
}
.padding(16)
}
}
关键代码讲解:
responseRegion({ x: -10, y: -10, width: 44, height: 44 })—— 扩大可点击区域到 44x44vpx: -10, y: -10—— 向左上各扩展 10vp,因为图标本身是 24x24,扩展后刚好 44x44- 视觉大小不变,但点击范围变大了——用户感知不到区别,但操作准确率大幅提升
测试验证方法
代码写完了,怎么验证无障碍是否生效?
- 开启读屏模式:设置 → 辅助功能 → 屏幕朗读,开启后触摸屏幕即可听到朗读内容
- 焦点导航:用音量键上下切换焦点,检查焦点顺序是否正确
- Accessibility Inspector:DevEco Studio 自带的检查工具,可以查看组件的无障碍属性
- 高对比度测试:设置 → 辅助功能 → 高对比度文字,开启后检查 UI 是否正常
快速自测清单:
- 所有图标按钮有
accessibilityText - 装饰性元素有
accessibilityLevel('no') - 表单焦点顺序正确
- 触摸目标 ≥ 44x44vp
- 高对比度模式下文字可读
写在最后
无障碍适配的 5 个改动,按优先级排:
- accessibilityText —— 最重要,没这个读屏就是瞎子
- 触摸目标扩大 —— 影响所有用户,不只是残障用户
- 焦点管理 —— 表单场景必做
- 朗读控制 —— 避免信息过载或遗漏
- 高对比度适配 —— 锦上添花但体现专业度
这 5 个改动加起来可能也就半天工作量,但对用户的体验提升是质的飞跃。别等应用商店强制要求了再补,现在就做。
更多推荐



所有评论(0)