跳到主要内容

Accessibility API 更新

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

动机

随着技术进步和移动应用在日常生活中变得越来越重要,创建可访问的应用的必要性也变得越来越重要。

React Native 有限的 Accessibility API 一直是开发者的巨大痛点,因此我们对 Accessibility API 进行了一些更新,以使其更易于创建包容性的移动应用。

现有 API 的问题

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

accessibilityComponentTypeaccessibilityTraits 是两个属性,用于告知 Android 上的 TalkBack 和 iOS 上的 VoiceOver 用户正在与哪种 UI 元素交互。这两个属性最大的问题是

  1. 它们是两个不同的属性,使用方法不同,但目的相同。 在之前的 API 中,这是两个独立的属性(每个平台一个),这不仅不方便,而且让许多开发者感到困惑。iOS 上的 accessibilityTraits 允许 17 个不同的值,而 Android 上的 accessibilityComponentType 仅允许 4 个值。此外,这些值在很大程度上没有重叠。甚至这两个属性的输入类型也不同。accessibilityTraits 允许传入 traits 数组或单个 trait,而 accessibilityComponentType 仅允许单个值。
  2. Android 上的功能非常有限。 使用旧属性,Talkback 能够识别的 UI 元素只有“button”、“radiobutton_checked”和“radiobutton_unchecked”。

问题二:不存在辅助功能提示:

辅助功能提示帮助使用 TalkBack 或 VoiceOver 的用户了解当他们在辅助功能元素上执行操作时会发生什么,而这并非仅凭辅助功能标签就能显而易见的。这些提示可以在设置面板中打开和关闭。以前,React Native 的 API 根本不支持辅助功能提示。

问题三:忽略反转颜色:

一些视力障碍用户在其手机上使用反转颜色以获得更高的屏幕对比度。Apple 为 iOS 提供了一个 API,允许开发者忽略某些视图。这样,当用户开启反转颜色设置时,图像和视频不会失真。React Native 目前不支持此 API。

新 API 的设计

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

为了解决 accessibilityComponentTypeaccessibilityTraits 之间的混淆,我们决定将它们合并为一个属性。这样做是有道理的,因为它们在技术上具有相同的预期功能,通过合并它们,开发者在构建辅助功能特性时不再需要担心平台特定的复杂性。

背景

在 iOS 上,UIAccessibilityTraits 是可以在任何 NSObject 上设置的属性。通过 javascript 属性传递到 native 的 17 个 traits 中的每一个都映射到 Objective-C 中的 UIAccessibilityTraits 元素。Traits 各自用一个长整数表示,并且每个设置的 trait 都进行 OR 运算。

然而在 Android 上,AccessibilityComponentType 是 React Native 创造的概念,并不直接映射到 Android 中的任何属性。辅助功能由辅助功能委托处理。每个视图都有一个默认的辅助功能委托。如果你想自定义任何辅助功能操作,你必须创建一个新的辅助功能委托,覆盖你想自定义的特定方法,然后将你正在处理的视图的辅助功能委托设置为与新的委托关联。当开发者设置 AccessibilityComponentType 时,native 代码会基于传入的组件创建一个新的委托,并将视图设置为具有该辅助功能委托。

所做的更改

对于我们的新属性,我们希望创建一个这两个属性的超集。我们决定将新属性主要模仿现有属性 accessibilityTraits 建模,因为 accessibilityTraits 具有明显更多的值。这些 traits 的 Android 功能将通过修改 Accessibility Delegate 进行 polyfill。

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

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

accessibilityRole

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

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

此属性仅允许传入一个值,因为 UI 元素通常在逻辑上不会承担多个角色。例外情况是图片和按钮,因此我们添加了一个角色 imagebutton,它是两者的组合。

accessibilityStates

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

  • 已选中
  • 已禁用

解决方案二:添加辅助功能提示

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

accessibilityHint

此属性接受要读取的辅助功能提示,格式为字符串。

在 iOS 上,设置此属性会将视图上相应的 native 属性 AccessibilityHint 设置为提示。然后,如果在 iPhone 中启用了辅助功能提示,Voiceover 将读取该提示。

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

我们在 Android 上做出此决定的原因是,通常,辅助功能提示与特定操作(例如,单击)相对应,并且我们希望保持跨平台行为的一致性。

问题三的解决方案

accessibilityIgnoresInvertColors

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

新的用法

这些新属性将在 React Native 0.57 版本中可用。

如何升级

如果你当前正在使用 accessibilityComponentTypeaccessibilityTraits,以下是你升级到新属性可以采取的步骤。

1. 使用 jscodeshift

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

这个 脚本 替换了以下实例

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

替换为

accessibilityRole= “trait”

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

2. 使用手动 codemod

对于使用 AccessibilityTraits 但没有 AccessibilityRole 对应值的情况,以及将多个 traits 传递到 AccessibilityTraits 的情况,必须手动完成 codemod。

一般来说,

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

将手动替换为

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

这些属性已在 Facebook 的代码库中使用。Facebook 的 codemod 非常简单。jscodeshift 脚本修复了我们大约一半的实例,另一半是手动修复的。总的来说,整个过程花费不到几个小时。

希望你会发现更新后的 API 很有用!并请继续制作可访问的应用!#inclusion