跳过主内容

无障碍功能 API 更新

·阅读 7 分钟
Ziqi Chen
加州大学伯克利分校学生

动机

随着技术的进步和移动应用在日常生活中变得越来越重要,创建无障碍应用程序的必要性也随之增长。

React Native 有限的无障碍功能 API 一直是开发人员的一个巨大痛点,因此我们对无障碍功能 API 进行了一些更新,以便更轻松地创建包容性移动应用程序。

现有 API 的问题

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

`accessibilityComponentType` 和 `accessibilityTraits` 是两个属性,用于告知 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)

为了解决 `accessibilityComponentType` 和 `accessibilityTraits` 之间的混淆,我们决定将它们合并为一个属性。这很有意义,因为它们在技术上具有相同的预期功能,通过合并它们,开发人员在构建无障碍功能时不再需要担心平台特定的复杂性。

背景

在 iOS 上,`UIAccessibilityTraits` 是一个可以设置在任何 `NSObject` 上的属性。通过 JavaScript 属性传递到原生的 17 个特性中的每一个都映射到 Objective-C 中的一个 `UIAccessibilityTraits` 元素。每个特性都由一个长整型表示,并且所有设置的特性都进行按位或操作。

然而,在 Android 上,`AccessibilityComponentType` 是 React Native 创建的一个概念,它不直接映射到 Android 中的任何属性。无障碍功能由无障碍委托处理。每个视图都有一个默认的无障碍委托。如果你想自定义任何无障碍操作,你必须创建一个新的无障碍委托,覆盖你想要自定义的特定方法,然后将你正在处理的视图的无障碍委托设置为与新委托关联。当开发人员设置 `AccessibilityComponentType` 时,原生代码会根据传入的组件创建一个新的委托,并设置视图以拥有该无障碍委托。

所做的更改

对于我们的新属性,我们希望创建这两个属性的超集。我们决定主要根据现有属性 `accessibilityTraits` 来建模新属性,因为 `accessibilityTraits` 具有明显更多的值。这些特性的 Android 功能将通过修改无障碍委托来进行 Polyfill(兼容性填充)。

iOS 上的 `accessibilityTraits` 可以设置为 17 个 `UIAccessibilityTraits` 值。然而,我们并没有将所有这些值都包含在新属性的可能值中。这是因为设置其中一些特性的效果实际上并不为人所熟知,而且许多这些值几乎从不使用。

`UIAccessibilityTraits` 的值通常有两种用途。它们要么描述 UI 元素的角色,要么描述 UI 元素所处的状态。我们观察到以前属性的大多数用法通常使用一个代表角色的值,并将其与“state selected”、“state disabled”或两者结合。因此,我们决定创建两个新的无障碍属性:`accessibilityRole` 和 `accessibilityState`。

accessibilityRole

新属性 `accessibilityRole` 用于告知 Talkback 或 Voiceover UI 元素的角色。此新属性可以取以下值之一

  • 按钮
  • 链接
  • 搜索
  • 图像
  • 键盘键
  • 文本
  • 可调整
  • 标题
  • 摘要
  • 图像按钮

此属性只允许传入一个值,因为 UI 元素通常在逻辑上不会同时拥有多个角色。图像和按钮是例外,因此我们添加了一个 `imagebutton` 角色,它是两者的组合。

accessibilityStates

新属性 `accessibilityStates` 用于告知 Talkback 或 Voiceover UI 元素所处的状态。此属性接受一个包含以下一个或两个值的数组

  • 已选择
  • 已禁用

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

为此,我们添加了一个新属性 `accessibilityHint`。设置此属性将允许 Talkback 或 Voiceover 向用户朗读提示。

accessibilityHint

此属性接受一个字符串形式的无障碍提示,用于朗读。

在 iOS 上,设置此属性将设置视图上相应的原生属性 `AccessibilityHint`。如果 iPhone 中开启了无障碍提示,Voiceover 将朗读该提示。

在 Android 上,设置此属性会将提示值附加到无障碍标签的末尾。这种实现方法的优点是它模仿了 iOS 上的提示行为,但缺点是这些提示无法像在 iOS 上那样在 Android 的设置中关闭。

我们在 Android 上做出此决定的原因是因为通常情况下,无障碍提示与特定操作(例如点击)相对应,我们希望保持跨平台行为的一致性。

问题三的解决方案

accessibilityIgnoresInvertColors

我们将 Apple 的 `AccessibilityIgnoresInvertColors` API 暴露给 JavaScript,因此现在当您有一个不希望颜色反转的视图(例如图像)时,您可以将此属性设置为 `true`,它就不会被反转。

新用法

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

如何升级

如果您目前正在使用 `accessibilityComponentType` 和 `accessibilityTraits`,以下是您可以升级到新属性的步骤。

1. 使用 `jscodeshift`

最简单的用例可以通过运行 `jscodeshift` 脚本来替换。

这个脚本替换了以下实例

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

替换为

accessibilityRole= “trait”

此脚本还会删除 `AccessibilityComponentType` 的实例(假设您在任何地方设置 `AccessibilityComponentType`,也会设置 `AccessibilityTraits`)。

2. 使用手动代码转换

对于使用了 `AccessibilityTraits` 但没有相应 `AccessibilityRole` 值的情况,以及将多个特性传递给 `AccessibilityTraits` 的情况,需要进行手动代码转换。

通常,

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

将手动替换为

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

这些属性已在 Facebook 的代码库中使用。Facebook 的代码转换出奇地简单。`jscodeshift` 脚本修复了大约一半的实例,另一半是手动修复的。总的来说,整个过程不到几个小时。

希望您会发现更新后的 API 有用!请继续使应用具有无障碍功能!#包容性