跳至主内容
版本:0.77

无障碍功能

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

Android 和 iOS 均提供 API 用于将应用与辅助技术(如系统内置的屏幕阅读器 VoiceOver(iOS)和 TalkBack(Android))集成。React Native 提供互补的 API,让您的应用能够服务所有用户。

信息

Android 和 iOS 的实现方式略有差异,因此 React Native 的无障碍功能实现可能因平台而异。

无障碍属性

accessible

当值为 true 时,表示该视图是一个无障碍元素。当视图被标记为无障碍元素时,它会将其子元素组合成单个可选择组件。默认情况下,所有可触摸元素都是无障碍的。

在 Android 上,react-native View 的 accessible={true} 属性会被转换为原生 focusable={true}

tsx
<View accessible={true}>
<Text>text one</Text>
<Text>text two</Text>
</View>

在上例中,无障碍焦点仅存在于带有 accessible 属性的父视图上,而不会单独作用于 "文本一" 和 "文本二"。

accessibilityLabel

当视图被标记为无障碍元素时,最佳实践是设置 accessibilityLabel 属性,这样使用 VoiceOver 或 TalkBack 的用户就能知道他们选择了什么元素。屏幕阅读器会在选中相关元素时朗读该字符串。

使用方式:在您的 View、Text 或 Touchable 组件上设置 accessibilityLabel 属性为自定义字符串:

tsx
<TouchableOpacity
accessible={true}
accessibilityLabel="Tap me!"
onPress={onPress}>
<View style={styles.button}>
<Text style={styles.buttonText}>Press me!</Text>
</View>
</TouchableOpacity>

在上例中,TouchableOpacity 元素的 accessibilityLabel 默认会是 "Press me!"。该标签由所有 Text 子节点通过空格连接构成。

accessibilityLabelledBy
Android

引用另一个元素的 nativeID 用于构建复杂表单。 accessibilityLabelledBy 的值应与关联元素的 nativeID 匹配:

tsx
<View>
<Text nativeID="formLabel">Label for Input Field</Text>
<TextInput
accessibilityLabel="input"
accessibilityLabelledBy="formLabel"
/>
</View>

在上例中,当焦点位于 TextInput 时,屏幕阅读器会播报 Input, Edit Box for Label for Input Field

accessibilityHint

当仅靠无障碍标签无法明确操作结果时,可使用无障碍提示为用户提供额外上下文信息。

在您的 View、Text 或 Touchable 组件上设置 accessibilityHint 属性为自定义字符串:

tsx
<TouchableOpacity
accessible={true}
accessibilityLabel="Go back"
accessibilityHint="Navigates to the previous screen"
onPress={onPress}>
<View style={styles.button}>
<Text style={styles.buttonText}>Back</Text>
</View>
</TouchableOpacity>
iOS

在上例中,如果用户在设备的 VoiceOver 设置中启用了提示功能,VoiceOver 会在朗读标签后播报提示。更多关于 accessibilityHint 的指南请参阅 iOS 开发者文档

Android

在上例中,TalkBack 会在标签后朗读提示。目前 Android 无法关闭提示功能。

accessibilityLanguage
iOS

通过 accessibilityLanguage 属性,屏幕阅读器能识别朗读元素的标签提示时应使用的语言。提供的字符串值必须遵循 BCP 47 规范

tsx
<View
accessible={true}
accessibilityLabel="Pizza"
accessibilityLanguage="it-IT">
<Text>🍕</Text>
</View>

accessibilityIgnoresInvertColors
iOS

屏幕颜色反转是 iOS 和 iPadOS 中为色盲、低视力或视力障碍用户提供的无障碍功能。如果您有不希望在此设置启用时反转的视图(例如照片),请将此属性设为 true

accessibilityLiveRegion
Android

当组件动态变化时,我们需要 TalkBack 通知最终用户。这可通过 accessibilityLiveRegion 属性实现,可设置为 nonepoliteassertive

  • none 无障碍服务不应播报此视图的变更。

  • polite 辅助服务应播报此视图的变更

  • assertive 无障碍服务应中断当前语音播报,立即宣布该视图的变更。

tsx
<TouchableWithoutFeedback onPress={addOne}>
<View style={styles.embedded}>
<Text>Click me</Text>
</View>
</TouchableWithoutFeedback>
<Text accessibilityLiveRegion="polite">
Clicked {count} times
</Text>

在上述示例中,addOne 方法改变了状态变量 count 的值。当用户触发 TouchableWithoutFeedback 组件时,由于 Text 视图设置了 accessibilityLiveRegion="polite" 属性,TalkBack 会朗读其中的文本内容。

accessibilityRole

accessibilityRole 用于向辅助技术用户传达组件的功能用途。

accessibilityRole 可选值包括:

  • adjustable 表示可调节元素(例如滑块)

  • alert 当元素包含需向用户展示的重要文本时使用

  • button 当元素应作为按钮处理时使用

  • checkbox 当元素代表可选中/未选中/混合状态的复选框时使用

  • combobox 当元素代表组合框(允许用户从多个选项中选择)时使用

  • header 表示作为内容区块标题的元素(例如导航栏标题)

  • image 表示应被视为图片的元素,可与按钮或链接组合使用

  • imagebutton 表示既是图片又应被视为按钮的元素

  • keyboardkey 表示充当键盘按键的元素

  • link 当元素应作为链接处理时使用

  • menu 当组件是选择菜单时使用

  • menubar 当组件是多个菜单的容器时使用

  • menuitem 代表菜单中的选项

  • none 当元素无预设角色时使用

  • progressbar 用于表示任务进度指示组件

  • radio 用于表示单选按钮。

  • radiogroup 用于表示一组单选按钮。

  • scrollbar 用于表示滚动条。

  • search 表示应同时被视为搜索框的文本输入框

  • spinbutton 用于表示可打开选项列表的按钮。

  • summary 用于在应用首次启动时提供当前状态的快速摘要。

  • switch 用于表示可开关的切换按钮。

  • tab 用于表示标签页。

  • tablist 用于表示标签页列表。

  • text 表示应被视为静态不可变文本的元素

  • timer 用于表示计时器。

  • togglebutton 表示切换按钮,需配合 accessibilityState 的 checked 值指示开关状态

  • toolbar 用于表示工具栏(操作按钮或组件的容器)。

  • grid 与 ScrollView、VirtualizedList、FlatList 或 SectionList 结合使用表示网格布局,为 Android GridView 添加网格进出播报

accessibilityShowsLargeContentViewer
iOS

布尔值属性,决定用户长按元素时是否显示大内容视图器

适用于 iOS 13.0 及以上版本

accessibilityLargeContentTitle
iOS

当大内容视图器显示时,该字符串将作为标题使用

需将 accessibilityShowsLargeContentViewer 设置为 true 生效

tsx
<View
accessibilityShowsLargeContentViewer={true}
accessibilityLargeContentTitle="Home Tab">
<Text>Home</Text>
</View>

accessibilityState

描述组件当前状态给辅助技术用户

accessibilityState 是一个对象,包含以下字段:

NameDescriptionTypeRequired
disabledIndicates whether the element is disabled or not.booleanNo
selectedIndicates whether a selectable element is currently selected or not.booleanNo
checkedIndicates the state of a checkable element. This field can either take a boolean or the "mixed" string to represent mixed checkboxes.boolean or 'mixed'No
busyIndicates whether an element is currently busy or not.booleanNo
expandedIndicates whether an expandable element is currently expanded or collapsed.booleanNo

使用时,将 accessibilityState 设置为符合特定定义的对象

accessibilityValue

表示组件的当前值。可以是组件值的文本描述,对于基于范围的组件(如滑块和进度条),则包含范围信息(最小值、当前值和最大值)

accessibilityValue 是一个对象,包含以下字段:

NameDescriptionTypeRequired
minThe minimum value of this component's range.integerRequired if now is set.
maxThe maximum value of this component's range.integerRequired if now is set.
nowThe current value of this component's range.integerNo
textA textual description of this component's value. Will override min, now, and max if set.stringNo

accessibilityViewIsModal
iOS

布尔值,指示 VoiceOver 是否应忽略接收者同级视图中的元素

例如,在包含同级视图 AB 的窗口中,将视图 BaccessibilityViewIsModal 设为 true 会使 VoiceOver 忽略视图 A 中的元素。而如果视图 B 包含子视图 C 并将 CaccessibilityViewIsModal 设为 true,VoiceOver 仍会处理视图 A 中的元素

accessibilityElementsHidden
iOS

布尔值,指示此无障碍元素内包含的子元素是否隐藏

例如,在包含同级视图 AB 的窗口中,将视图 BaccessibilityElementsHidden 设为 true 会使 VoiceOver 忽略视图 B 内的元素。这类似于 Android 的 importantForAccessibility="no-hide-descendants" 属性

aria-valuemax

表示基于范围的组件(如滑块和进度条)的最大值

aria-valuemin

表示基于范围的组件(如滑块和进度条)的最小值

aria-valuenow

表示基于范围的组件(如滑块和进度条)的当前值

aria-valuetext

表示组件的文本描述

aria-busy

表示元素正在更新中,辅助技术可能需要等待变更完成后再通知用户。

TypeDefault
booleanfalse

aria-checked

表示可勾选元素的状态。该字段可接受布尔值或 "mixed" 字符串(表示混合状态的复选框)。

TypeDefault
boolean, 'mixed'false

aria-disabled

表示元素可见但处于禁用状态,因此不可编辑或操作。

TypeDefault
booleanfalse

aria-expanded

指示可展开元素当前是展开还是折叠状态。

TypeDefault
booleanfalse

aria-hidden

表示此无障碍元素内包含的子元素是否隐藏

例如,在包含同级视图 AB 的窗口中,将视图 Baria-hidden 设为 true 会使 VoiceOver 忽略视图 B 内的元素

TypeDefault
booleanfalse

aria-label

定义用于标记交互元素的字符串值。

Type
string

aria-labelledby
Android

标识标记当前元素的关联元素。aria-labelledby 的值应匹配关联元素的 nativeID

tsx
<View>
<Text nativeID="formLabel">Label for Input Field</Text>
<TextInput aria-label="input" aria-labelledby="formLabel" />
</View>
Type
string

aria-live
Android

表示元素将被更新,并描述用户代理、辅助技术和用户可预期的实时区域更新类型

  • off 辅助服务不应播报此视图的变更

  • polite 辅助服务应播报此视图的变更

  • assertive 无障碍服务应中断当前语音播报,立即宣布该视图的变更。

TypeDefault
enum('assertive', 'off', 'polite')'off'

aria-modal
iOS

布尔值,指示 VoiceOver 是否应忽略接收器同级视图内的元素。

TypeDefault
booleanfalse

aria-selected

指示可选元素当前是否被选中。

Type
boolean

importantForAccessibility
Android

当两个具有相同父级的重叠UI组件并存时,默认的无障碍焦点可能出现不可预测行为。importantForAccessibility 属性通过控制视图是否触发无障碍事件及是否上报无障碍服务来解决此问题。可选值包括 auto(自动)、yes(是)、no(否)和 no-hide-descendants(最后一个值会强制无障碍服务忽略该组件及其所有子元素)。

tsx
<View style={styles.container}>
<View
style={[styles.layout, {backgroundColor: 'green'}]}
importantForAccessibility="yes">
<Text>First layout</Text>
</View>
<View
style={[styles.layout, {backgroundColor: 'yellow'}]}
importantForAccessibility="no-hide-descendants">
<Text>Second layout</Text>
</View>
</View>

在上述示例中,yellow 布局及其子元素对 TalkBack 和所有其他无障碍服务完全不可见。这样我们就能使用具有相同父级的重叠视图而不会混淆 TalkBack。

onAccessibilityEscape
iOS

将此属性分配给自定义函数,当用户执行"退出"手势(双指 Z 形滑动)时触发。退出函数应在用户界面中按层级回退,例如在导航结构中向上/返回或关闭模态界面。若选定元素无 onAccessibilityEscape 函数,系统将尝试向上遍历视图层级直至找到有效视图,否则发出提示音表示未找到。

onAccessibilityTap
iOS

使用此属性为无障碍元素分配自定义函数,当用户选中该元素并双击激活时触发。

onMagicTap
iOS

将此属性分配给自定义函数,当用户执行"魔法点击"手势(双指双击)时触发。魔法点击函数应执行组件上最相关的用户操作。例如 iPhone 电话应用中,魔法点击可接听或挂断电话。若选定元素无 onMagicTap 函数,系统将向上遍历视图层级直至找到有效视图。

role

role 用于传达组件的用途,优先级高于 accessibilityRole 属性。

role 可选值如下:

  • alert 当元素包含需向用户展示的重要文本时使用

  • button 当元素应作为按钮处理时使用

  • checkbox 当元素代表可选中/未选中/混合状态的复选框时使用

  • combobox 当元素代表组合框(允许用户从多个选项中选择)时使用

  • grid 与 ScrollView、VirtualizedList、FlatList 或 SectionList 结合使用表示网格布局,为 Android GridView 添加网格内/外播报功能

  • heading 当元素作为内容区块标题时使用(例如导航栏标题)

  • img 当元素应作为图片处理时使用,可与按钮或链接等组合

  • link 当元素应作为链接处理时使用

  • list 用于标识项目列表

  • listitem 用于标识列表中的项目

  • menu 当组件是选择菜单时使用

  • menubar 当组件是多个菜单的容器时使用

  • menuitem 代表菜单中的选项

  • none 当元素无预设角色时使用

  • presentation 当元素无预设角色时使用(与 none 同义)

  • progressbar 用于表示任务进度指示组件

  • radio 用于表示单选按钮。

  • radiogroup 用于表示一组单选按钮。

  • scrollbar 用于表示滚动条。

  • searchbox 当文本框元素需要同时被视为搜索框时使用。

  • slider 用于可"调节"的元素(例如滑块)。

  • spinbutton 用于表示可打开选项列表的按钮。

  • summary 用于在应用首次启动时提供当前状态的快速摘要。

  • switch 用于表示可开关的切换按钮。

  • tab 用于表示标签页。

  • tablist 用于表示标签页列表。

  • timer 用于表示计时器。

  • toolbar 用于表示工具栏(操作按钮或组件的容器)。

无障碍操作

无障碍操作允许辅助技术以编程方式触发组件的操作。组件需要完成以下两个步骤来支持无障碍操作:

  • 通过 accessibilityActions 属性定义支持的操作列表

  • 实现 onAccessibilityAction 函数来处理操作请求

accessibilityActions 属性应包含操作对象列表,每个操作对象需包含以下字段:

NameTypeRequired
namestringYes
labelstringNo

操作既可以是标准操作(如点击按钮或调节滑块),也可以是特定组件的自定义操作(如删除邮件)。标准操作和自定义操作都必须提供 name 字段,但标准操作的 label 是可选的。

添加标准操作支持时,name 必须是以下值之一:

  • 'magicTap' - 仅限 iOS - 当 VoiceOver 焦点位于组件上或内部时,用户用双指双击

  • 'escape' - 仅限 iOS - 当 VoiceOver 焦点位于组件上或内部时,用户执行双指擦除手势(左-右-左)

  • 'activate' - 激活组件。无论是否使用辅助技术,都应执行相同操作。屏幕阅读器用户双击组件时触发

  • 'increment' - 增加可调节组件的值。在 iOS 上,当组件角色为 'adjustable' 且用户聚焦后上滑时,VoiceOver 会生成此操作。在 Android 上,当用户将无障碍焦点置于组件并按下音量增大键时,TalkBack 会生成此操作

  • 'decrement' - 减少可调节组件的值。在 iOS 上,当组件角色为 'adjustable' 且用户聚焦后下滑时,VoiceOver 会生成此操作。在 Android 上,当用户将无障碍焦点置于组件并按下音量减小键时,TalkBack 会生成此操作

  • 'longpress' - 仅限 Android - 当用户将无障碍焦点置于组件上,然后双击并长按屏幕时生成此操作。无论是否使用辅助技术,都应执行相同操作

label 字段对标准操作是可选的(辅助技术通常不使用),对于自定义操作则是包含操作描述的本地化字符串,将展示给用户

要处理操作请求,组件必须实现 onAccessibilityAction 函数。该函数唯一参数是包含待执行操作名称的事件对象。以下来自 RNTester 的示例展示了如何创建定义和处理多个自定义操作的组件

tsx
<View
accessible={true}
accessibilityActions={[
{name: 'cut', label: 'cut'},
{name: 'copy', label: 'copy'},
{name: 'paste', label: 'paste'},
]}
onAccessibilityAction={event => {
switch (event.nativeEvent.actionName) {
case 'cut':
Alert.alert('Alert', 'cut action success');
break;
case 'copy':
Alert.alert('Alert', 'copy action success');
break;
case 'paste':
Alert.alert('Alert', 'paste action success');
break;
}
}}
/>

检测屏幕阅读器是否启用

AccessibilityInfo API 可用于判断屏幕阅读器当前是否处于激活状态。详情请参阅 AccessibilityInfo 文档

Sending Accessibility Events
Android

有时需要在 UI 组件上触发辅助功能事件(例如自定义视图出现时或为视图设置无障碍焦点)。原生 UIManager 模块为此提供了 'sendAccessibilityEvent' 方法,接收两个参数:视图标签和事件类型。支持的事件类型包括 typeWindowStateChangedtypeViewFocusedtypeViewClicked

tsx
import {Platform, UIManager, findNodeHandle} from 'react-native';

if (Platform.OS === 'android') {
UIManager.sendAccessibilityEvent(
findNodeHandle(this),
UIManager.AccessibilityEventTypes.typeViewFocused,
);
}

Testing TalkBack Support
Android

要启用 TalkBack,请打开 Android 设备或模拟器上的"设置"应用,依次点击"无障碍"→"TalkBack",切换"使用服务"开关即可启用/禁用。

Android 模拟器默认不安装 TalkBack。可通过 Google Play 商店安装:确保选择带 Google Play 商店的模拟器(在 Android Studio 中可用)。

可使用音量键快捷操作开关 TalkBack:进入"设置"→"无障碍",开启顶部的"音量键快捷操作"。

启用快捷操作后,长按两个音量键 3 秒即可启动无障碍工具。

此外也可通过命令行开关 TalkBack:

shell
# disable
adb shell settings put secure enabled_accessibility_services com.android.talkback/com.google.android.marvin.talkback.TalkBackService

# enable
adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService

Testing VoiceOver Support
iOS

要在 iOS/iPadOS 设备启用 VoiceOver:打开"设置"→"通用"→"辅助功能",在"视觉"区域找到 VoiceOver 并切换顶部开关。

在辅助功能设置底部有"辅助功能快捷键",可通过三击 Home 键开关 VoiceOver。

模拟器不支持 VoiceOver,但可使用 Xcode 的 Accessibility Inspector 通过 macOS 的 VoiceOver 测试。注意:实际设备测试更可靠,因 macOS 的 VoiceOver 体验可能不同。

扩展资源