1. 无障碍属性概述

1.1 定义与作用

无障碍属性 是附着在 UI 组件上的额外语义数据,用于向 辅助功能服务(如 TalkBack、Switch Access)描述组件的角色、状态、行为与操作说明。作用可概括为三点:

  • 替代视觉通道:让非视觉用户通过听觉或触觉感知界面结构与内容。
  • 提供操作上下文:告知系统组件支持哪些交互(点击、长按、滑动、自定义手势)。
  • 保证语义一致性:使自定义绘制的组件与原生组件在无障碍层面表现一致。
有/无障碍属性对比
场景无属性有属性 (contentDescription + role)
TalkBack 焦点无焦点,直接跳过可获得焦点,朗读内容
手势识别无法触发自定义操作可映射为无障碍 Action
屏幕阅读器理解视为不可见元素明确知道是按钮/滑块/开关

1.2 Compose 无障碍模型

Compose 采用 语义树(Semantic Tree) 作为无障碍信息的中枢。每个 Composable 节点可以向语义树提交一个 SemanticsPropertyReceiver 块,其中包含角色、标签、状态、操作等属性。辅助功能服务通过平台桥接层读取这棵树,无需直接访问底层 View 系统。

核心流程:
Composable 渲染 → 语义节点聚合 → 语义树构建 → 平台适配层 → 辅助功能服务消费

关键 API 入口是 Modifier.semantics {} 和 Modifier.clearAndSetSemantics {}:

// 为自定义组件添加无障碍语义
Modifier.semantics {
    contentDescription = "播放按钮"
    role = Role.Button
    onClick(label = "播放", action = { playMusic() })
}

1.3 关键属性列表

下表列出 Compose 中最常用、必须掌握的无障碍属性,后续章节会逐一深入实现细节:

属性作用类型/值默认来源
contentDescription组件朗读文本String无
role语义角色(按钮、图片、开关等)Role 枚举部分 Material 组件自带
stateDescription状态描述(已选择、已禁用等)String无
progressBarRangeInfo进度条范围与当前进度ProgressBarRangeInfo无
isTraversalGroup是否强制组内焦点遍历Boolean无
isHeading标记为标题Boolean无
onClick / onLongClick自定义点击无障碍操作(() -> Unit)多数默认可点击组件
testTag测试 & 无障碍索引标签String无
常见误区:仅设置 contentDescription 而不指定 role,TalkBack 只能读文本但无法告知用户该元素可点击或可滑动。自定义组件必须明确 role 和对应的操作回调。

1.4 无障碍属性分类与数据流

下面的 SVG 展示了无障碍属性在 Compose 中的分类层级与从组件到辅助服务的完整数据流路径:

Compose 无障碍属性分类与数据流 语义化角色 (Role) 内容描述 状态信息 操作绑点 语义树 (Semantic Tree) 聚合所有节点的 semantics 数据 Android 平台无障碍桥接 (AccessibilityNodeInfo) 辅助功能服务 (TalkBack / Switch Access) 朗读描述 · 触发操作 · 反馈状态变化 用户自定义组件通过 Modifier.semantics {} 向语义树注册属性,平台桥接保证兼容性

1.5 调试与验证

开发阶段快速检查语义属性是否正确:

  1. 开启 TalkBack:系统设置 → 无障碍 → TalkBack,滑动到自定义组件并听取朗读内容。
  2. 使用 Accessibility Scanner:Play 商店下载,扫描界面后会报告缺失的 contentDescription、角色冲突等。
  3. Layout Inspector + Accessibility Tree:Android Studio → Tools → Layout Inspector → 选择 Accessibility Tree 视图,逐节点审查语义数据。
// 单元测试中验证语义属性
@Test
fun customButton_hasCorrectSemantics() {
    composeTestRule.setContent {
        CustomButton(onClick = {})
    }
    composeTestRule.onNodeWithTag("custom_btn")
        .assertContentDescription("播放")
        .assertHasClickAction()
}

1.6 本节要点

  • 无障碍属性是辅助服务理解自定义组件的唯一桥梁,缺失将导致组件对非视觉用户完全不可用。
  • Compose 语义树是 MVVM 风格的描述式无障碍方案,Modifier.semantics {} 是核心注入点。
  • 关键属性分为四类:角色、描述、状态、操作;角色 + 描述 + 操作 是自定义组件最少必须提供的组合。
  • 利用 TalkBack、Accessibility Scanner、Layout Inspector 三个工具可高效验证属性配置是否正确。