鸿蒙多功能工具箱开发实战(二十六)-无障碍访问支持
·
鸿蒙多功能工具箱开发实战(二十六)-无障碍访问支持
前言
无障碍访问是应用包容性的重要体现,帮助视障、听障等用户群体更好地使用应用。本文将讲解HarmonyOS无障碍功能的实现。
一、无障碍基础
1.1 无障碍属性
ArkUI组件支持以下无障碍属性:
| 属性 | 说明 |
|---|---|
| accessibilityText | 无障碍文本 |
| accessibilityDescription | 无障碍描述 |
| accessibilityLevel | 无障碍等级 |
| accessibilityGroup | 是否为无障碍组 |
1.2 基础用法
@Entry
@Component
struct AccessiblePage {
build() {
Column() {
// 图片添加无障碍描述
Image($r('app.media.icon'))
.width(48)
.height(48)
.accessibilityText('应用图标')
.accessibilityDescription('多功能工具箱应用图标')
// 按钮添加无障碍支持
Button('计算')
.accessibilityText('计算按钮')
.accessibilityDescription('点击此按钮开始计算')
.onClick(() => {
// 计算逻辑
})
// 输入框添加提示
TextInput({ placeholder: '请输入金额' })
.accessibilityText('金额输入框')
.accessibilityDescription('请输入需要计算的金额')
}
}
}
二、无障碍组件封装
2.1 无障碍按钮
/**
* 无障碍按钮组件
*/
@Component
export struct AccessibleButton {
@Prop text: string = ''
@Prop accessibilityLabel: string = ''
@Prop accessibilityHint: string = ''
@Prop disabled: boolean = false
onButtonClick: () => void = () => {}
build() {
Button(this.text)
.enabled(!this.disabled)
.accessibilityText(this.accessibilityLabel || this.text)
.accessibilityDescription(this.accessibilityHint)
.accessibilityLevel(this.disabled ? 'no' : 'yes')
.onClick(() => {
if (!this.disabled) {
this.onButtonClick()
}
})
}
}
2.2 无障碍图片
/**
* 无障碍图片组件
*/
@Component
export struct AccessibleImage {
@Prop src: Resource | string = ''
@Prop alt: string = ''
@Prop description: string = ''
@Prop width: number = 100
@Prop height: number = 100
build() {
Image(this.src)
.width(this.width)
.height(this.height)
.alt(this.alt) // 图片加载失败时的替代文本
.accessibilityText(this.alt)
.accessibilityDescription(this.description)
}
}
2.3 无障碍列表项
/**
* 无障碍列表项
*/
@Component
export struct AccessibleListItem {
@Prop title: string = ''
@Prop subtitle: string = ''
@Prop icon: string = ''
onItemClick: () => void = () => {}
build() {
Row() {
if (this.icon) {
Text(this.icon)
.fontSize(24)
.margin({ right: 12 })
}
Column() {
Text(this.title)
.fontSize(16)
if (this.subtitle) {
Text(this.subtitle)
.fontSize(12)
.fontColor('#999999')
.margin({ top: 4 })
}
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
Text('›')
.fontSize(20)
.fontColor('#999999')
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
// 无障碍支持
.accessibilityGroup(true)
.accessibilityText(`${this.title},${this.subtitle}`)
.accessibilityDescription('双击进入')
.onClick(() => {
this.onItemClick()
})
}
}
三、屏幕阅读器支持
3.1 焦点管理
@Entry
@Component
struct FocusManagementPage {
@State focusIndex: number = 0
build() {
Column() {
// 焦点顺序控制
Button('按钮1')
.tabIndex(1)
.defaultFocus(true) // 默认焦点
.onClick(() => {})
Button('按钮2')
.tabIndex(2)
.onClick(() => {})
Button('按钮3')
.tabIndex(3)
.onClick(() => {})
// 跳过装饰性元素
Image($r('app.media.decoration'))
.accessibilityLevel('no') // 屏幕阅读器跳过
}
}
}
3.2 实时区域通知
/**
* 无障碍通知组件
*/
@Component
export struct AccessibleAnnouncement {
@State message: string = ''
@State isVisible: boolean = false
/**
* 显示通知
*/
show(msg: string): void {
this.message = msg
this.isVisible = true
// 3秒后自动隐藏
setTimeout(() => {
this.isVisible = false
}, 3000)
}
build() {
if (this.isVisible) {
Text(this.message)
.width('100%')
.height(48)
.backgroundColor('#333333')
.fontColor('#FFFFFF')
.textAlign(TextAlign.Center)
// 实时区域,屏幕阅读器会自动播报
.accessibilityLiveRegion('polite')
}
}
}
四、最佳实践
4.1 语义化结构
@Entry
@Component
struct SemanticPage {
build() {
Column() {
// 标题区域
Column() {
Text('计算结果')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.accessibilityRole('header')
}
.accessibilityGroup(true)
// 内容区域
Column() {
Text('税后工资: 12000元')
.accessibilityRole('text')
Text('应纳税额: 500元')
.accessibilityRole('text')
}
.accessibilityGroup(true)
.accessibilityText('计算结果详情')
// 操作区域
Row() {
Button('保存')
.accessibilityRole('button')
Button('分享')
.accessibilityRole('button')
}
.accessibilityGroup(true)
.accessibilityText('操作按钮')
}
}
}
4.2 状态变化通知
@Entry
@Component
struct StateAnnouncementPage {
@State loading: boolean = false
@State result: string = ''
async calculate() {
this.loading = true
// 通知用户正在加载
this.announce('正在计算,请稍候')
await this.doCalculate()
this.loading = false
this.result = '计算完成'
// 通知用户结果
this.announce('计算完成,结果是' + this.result)
}
private announce(message: string) {
// 使用无障碍API播报
// 实际实现需要调用系统无障碍服务
}
build() {
Column() {
if (this.loading) {
LoadingProgress()
.accessibilityText('正在计算')
} else {
Text(this.result)
.accessibilityText('计算结果: ' + this.result)
}
}
}
}
五、高级无障碍功能
5.1 无障碍流程图
5.2 手势支持
@Component
struct AccessibleGesture {
onDoubleTap: () => void
build() {
Text('双击激活')
.accessibilityText('双击此按钮激活功能')
.gesture(
TapGesture({ count: 2 })
.onAction(() => this.onDoubleTap())
)
}
}
5.3 键盘导航
@Component
struct KeyboardNavigation {
@State focusedIndex: number = 0
build() {
Column() {
ForEach(['选项1', '选项2', '选项3'], (item: string, index: number) => {
Text(item)
.focusable(true)
.defaultFocus(index === this.focusedIndex)
.onKeyEvent((event) => {
if (event.keyCode === KeyCode.KEYCODE_DPAD_DOWN) {
this.focusedIndex = Math.min(this.focusedIndex + 1, 2)
}
})
})
}
}
}
图 1 无障碍设置页面选择是否启用
六、小结
本文详细讲解了无障碍支持:
- ✅ 无障碍属性使用
- ✅ 无障碍组件封装
- ✅ 焦点管理
- ✅ 屏幕阅读器支持
- ✅ 语义化结构
- ✅ 手势支持
- ✅ 键盘导航
系列文章导航:
下期预告:鸿蒙多功能工具箱开发实战(二十七)-安全加固与数据保护
更多推荐


所有评论(0)