跳至主要内容

无障碍 API 更新

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

动机

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

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 唯一能够识别的 UI 元素是“button”、“radiobutton_checked”和“radiobutton_unchecked”。

问题二:不存在的无障碍提示:

无障碍提示帮助使用 TalkBack 或 VoiceOver 的用户了解当他们在不明显的无障碍元素上执行操作时会发生什么。这些提示可以在设置面板中打开和关闭。以前,React Native 的 API 完全不支持无障碍提示。

问题三:忽略反转颜色:

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

新 API 的设计

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

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

背景

在 iOS 中,UIAccessibilityTraits 是可以设置在任何 NSObject 上的属性。通过 JavaScript 属性传递到本地的每个 17 个特征都会映射到 Objective-C 中的 UIAccessibilityTraits 元素。每个特征都由一个长整型表示,并且设置的每个特征都会进行按位或运算。

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

做出的更改

对于我们的新属性,我们希望创建一个这两个属性的超集。我们决定使新属性主要基于现有的属性 accessibilityTraits 进行建模,因为 accessibilityTraits 具有更多值。通过修改无障碍委托,将为这些特征的 Android 功能提供填充。

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

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

accessibilityRole

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

  • none
  • button
  • link
  • search
  • image
  • keyboardkey
  • text
  • adjustable
  • header
  • summary
  • imagebutton

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

accessibilityStates

新属性 accessibilityStates 用于告诉 Talkback 或 Voiceover UI 元素所处的状态。此属性采用包含以下值之一或两者值的数组

  • selected
  • disabled

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

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

accessibilityHint

此属性以字符串的形式接收要读取的辅助功能提示。

在 iOS 上,设置此属性将设置视图上相应的原生属性 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. 使用手动代码修改

对于使用 AccessibilityTraits 但没有对应 AccessibilityRole 值的用例,以及将多个特征传递给 AccessibilityTraits 的用例,则必须进行手动代码修改。

一般来说,

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

将手动替换为

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

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

希望您会发现更新后的 API 有用!并请继续开发无障碍应用!#inclusion