跳到主要内容

辅助功能 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 元素是“按钮”、“单选按钮已选中”和“单选按钮未选中”。

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

无障碍提示可帮助使用 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 元素。特性由长整型表示,所有设置的特性都通过按位或运算组合在一起。

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

所做的更改

对于我们的新属性,我们希望创建这两个属性的超集。我们决定主要以现有属性 accessibilityTraits 为蓝本设计新属性,因为 accessibilityTraits 的值明显更多。Android 对这些特性的功能将通过修改无障碍委托进行兼容。

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

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

accessibilityRole

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

  • 按钮
  • 链接
  • 搜索
  • 图片
  • 键盘键
  • 文本
  • 可调整
  • 标题
  • 总结
  • 图片按钮

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

辅助功能状态

新属性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. 使用手动代码转换

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

通常,

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

将被手动替换为

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

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

希望您会发现更新后的API很有用!并请继续让应用程序无障碍!#包容