跳至主内容

无障碍 API 更新

· 1 分钟阅读
Ziqi Chen
加州大学伯克利分校学生
非官方测试版翻译

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

背景动机

随着技术进步和移动应用在日常生活中日益重要,开发无障碍应用的需求也变得越来越迫切。

React Native 有限的无障碍 API 一直是开发者的痛点,因此我们对无障碍 API 进行了多项更新,让创建包容性移动应用更加便捷。

现有 API 的问题

问题一:两个相似却不同的属性 - accessibilityComponentType (Android) 和 accessibilityTraits (iOS)

accessibilityComponentTypeaccessibilityTraits 用于告知 Android 的 TalkBack 和 iOS 的 VoiceOver 用户正在交互的 UI 元素类型。这两个属性存在两大问题:

  1. 功能相同却使用两套不同机制。旧 API 中这两个平台专属属性不仅使用不便,还给开发者带来困惑。iOS 的 accessibilityTraits 支持 17 种值,而 Android 的 accessibilityComponentType 仅支持 4 种值,且多数值不重叠。更麻烦的是输入格式也不同:accessibilityTraits 支持数组或单值,而 accessibilityComponentType 仅接受单值。

  2. Android 功能极其有限。旧属性下 TalkBack 只能识别 "button"、"radiobutton_checked" 和 "radiobutton_unchecked" 三种 UI 元素。

问题二:缺失无障碍提示

当无障碍标签无法明确表达操作结果时,无障碍提示能帮助使用 TalkBack 或 VoiceOver 的用户理解操作效果。这些提示可在设置中开关,但 React Native 的旧 API 完全不支持此功能。

问题三:忽略颜色反转

部分视障用户会开启手机颜色反转功能增强对比度。Apple 提供了允许开发者忽略特定视图的 iOS API,确保开启颜色反转时图片视频不变形,但 React Native 此前未支持该 API。

新 API 设计

解决方案一:整合 accessibilityComponentType (Android) 和 accessibilityTraits (iOS)

为解决 accessibilityComponentTypeaccessibilityTraits 之间的混淆问题,我们将其合并为单一属性。这符合逻辑——两者功能本质相同,合并后开发者无需再考虑平台差异。

技术背景

iOS 中,UIAccessibilityTraits 是可设置于任何 NSObject 的属性。通过 JavaScript 传到原生层的 17 种特性会映射到 Objective-C 的 UIAccessibilityTraits 元素。每个特性用长整型表示,多特性通过按位或(OR)组合。

Android 的 AccessibilityComponentType 则是 React Native 自创概念,不直接对应 Android 原生属性。Android 通过无障碍委托处理:每个视图有默认委托,如需定制需创建新委托并覆盖特定方法。当开发者设置 AccessibilityComponentType 时,原生代码会根据传入组件创建新委托。

具体变更

新属性旨在成为两属性的超集。我们决定新属性主要基于现有属性 accessibilityTraits 进行建模,因为 accessibilityTraits 的值要多得多。这些特性的功能将通过修改无障碍委托在 Android 上实现。

accessibilityTraits 在 iOS 支持 17 种值,但新属性未全采纳。因部分特性效果不明确,且许多值实际极少使用。

这些特性值通常体现两种用途:描述 UI 元素角色或状态。观察发现,开发者通常组合一个角色值(如 "button")与状态值(如 "selected" 或 "disabled")。因此我们拆分出两个新属性:accessibilityRoleaccessibilityState

accessibilityRole

新属性 accessibilityRole 用于向 TalkBack 或 VoiceOver 说明 UI 元素角色,支持以下值:

  • none

  • button

  • link

  • search

  • image

  • keyboardkey

  • text

  • adjustable

  • header

  • summary

  • imagebutton

此属性仅接受单值,因 UI 元素通常不承担多重角色。特例是图片(image)和按钮(button)的组合,故新增了 imagebutton 角色。

accessibilityStates

新属性 accessibilityStates 用于说明 UI 元素状态,接受包含以下一个或多个值的数组:

  • selected

  • disabled

解决方案二:添加无障碍提示

我们新增 accessibilityHint 属性,设置后 TalkBack 或 VoiceOver 将向用户朗读提示内容。

accessibilityHint

此属性接受字符串形式的无障碍提示内容。

iOS 中设置该属性会同步原生视图的 AccessibilityHint 属性,当 iPhone 开启无障碍提示时 VoiceOver 将朗读。

Android 的实现是将提示内容追加到无障碍标签末尾。这样做模拟了 iOS 的行为,但缺点是 Android 无法像 iOS 那样在设置中单独关闭提示。

此设计源于无障碍提示通常对应特定操作(如点击),我们希望保持跨平台行为一致。

问题三解决方案

accessibilityIgnoresInvertColors

我们将 Apple 的 AccessibilityIgnoresInvertColors API 暴露给 JavaScript。现在当您有不希望颜色反转的视图(如图片)时,设置此属性为 true 即可避免反转。

使用方式

这些新属性将在 React Native 0.57 版本中提供。

升级指南

若您当前正在使用 accessibilityComponentTypeaccessibilityTraits,可按以下步骤迁移到新属性。

方法一:使用 jscodeshift 工具

简单场景可通过运行 jscodeshift 脚本完成替换。

脚本可自动替换以下情况:

accessibilityTraits=“trait”
accessibilityTraits={[“trait”]}

accessibilityRole= “trait”

该脚本还会移除 AccessibilityComponentType 实例(假设您每次设置 AccessibilityComponentType 时都会同时设置 AccessibilityTraits)。

方法二:手动代码替换

对于 AccessibilityTraits 使用无对应 AccessibilityRole 值的情况,以及将多个特征值传递到 AccessibilityTraits 的情况,需要手动修改。

通常而言,

accessibilityTraits= {[“button”, “selected”]}

需手动替换为

accessibilityRole=“button”
accessibilityStates={[“selected”]}

这些属性已在 Facebook 代码库中实际应用。令人惊喜的是,Facebook 的代码迁移相当简单:jscodeshift 脚本处理了约半数实例,其余手动修改,整个过程仅耗时数小时。

希望新版 API 能为您带来便利!请持续打造无障碍应用!#包容性设计