无障碍(Accessibility)是现代应用开发的重要组成部分。Compose 提供了强大的语义系统(Semantics),让你可以轻松构建对屏幕阅读器和辅助服务友好的 UI。
💡 无障碍带来的好处
扩大用户群体、提升所有用户体验、符合法规要求(ADA、WCAG)、提升可测试性。
一、Semantics 语义系统
// 为图标提供描述
Icon(
imageVector = Icons.Default.Share,
contentDescription = "分享"
)
// 装饰性图像
Image(
painter = painterResource(R.drawable.decorative),
contentDescription = null // 会被忽略
)
二、自定义语义
Box(
modifier = Modifier
.clickable { onItemClick() }
.semantics {
role = Role.Button
contentDescription = "自定义按钮"
}
) {
Text("点击我")
}
状态描述
@Composable
fun ExpandableCard(expanded: Boolean) {
Column(
modifier = Modifier.semantics {
stateDescription = if (expanded) "已展开" else "已折叠"
}
) { ... }
}
三、合并语义
@Composable
fun UserCard(user: User) {
Row(
modifier = Modifier
.clickable { onUserClick(user) }
.clearAndSetSemantics {
contentDescription = "${user.name},${user.role},点击查看详情"
}
) {
Avatar(user.avatarUrl)
Text(user.name)
}
}
四、自定义操作
Box(
modifier = Modifier.semantics {
customActions = listOf(
CustomAccessibilityAction("删除") {
onDelete()
true
},
CustomAccessibilityAction("归档") {
onArchive()
true
}
)
}
) { ... }
五、Live Region
Text(
text = "计数: $count",
modifier = Modifier.semantics {
liveRegion = LiveRegionMode.Polite // 内容变化时通知
}
)
六、最佳实践清单
- ✅ 为所有有意义的图标提供
contentDescription - ✅ 装饰性图像使用
contentDescription = null - ✅ 使用
mergeDescendants合并相关元素 - ✅ 为复杂手势提供替代的
customActions - ✅ 确保触摸目标至少 48dp
- ✅ 使用
heading()标记标题 - ✅ 使用 TalkBack 实际测试
总结
- Semantics:向辅助服务描述 UI
- contentDescription:为图像提供描述
- Role:明确元素交互类型
- customActions:为手势提供替代操作
- liveRegion:通知动态内容变化