辅助功能 API 更新
动机
随着技术的进步和移动应用在日常生活中变得越来越重要,创建无障碍应用的需求也同样变得越来越重要。
React Native有限的无障碍API一直是开发人员的一大痛点,因此我们对无障碍API进行了一些更新,使其更容易创建包容性移动应用。
现有API的问题
问题一:两个完全不同但相似的属性 - accessibilityComponentType (Android) 和 accessibilityTraits (iOS)
accessibilityComponentType
和 accessibilityTraits
是两个属性,用于告诉 Android 上的 TalkBack 和 iOS 上的 VoiceOver 用户正在与哪种 UI 元素进行交互。这些属性的两个最大问题是:
- 它们是具有不同使用方法的两个不同属性,但目的相同。在以前的 API 中,它们是两个独立的属性(每个平台一个),这不仅不方便,而且让许多开发人员感到困惑。iOS 上的
accessibilityTraits
允许 17 种不同的值,而 Android 上的accessibilityComponentType
只允许 4 种值。此外,这些值在很大程度上没有重叠。甚至这两个属性的输入类型也不同。accessibilityTraits
允许传入一个特性数组或单个特性,而accessibilityComponentType
只允许单个值。 - Android上的功能非常有限。使用旧属性,Talkback 唯一能识别的 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
元素。特性由长整型表示,并且每个设置的特性都进行 OR 运算。
然而,在 Android 上,AccessibilityComponentType
是 React Native 创建的一个概念,它不直接映射到 Android 中的任何属性。无障碍性由无障碍委托处理。每个视图都有一个默认的无障碍委托。如果你想自定义任何无障碍操作,你必须创建一个新的无障碍委托,重写你想自定义的特定方法,然后将你正在处理的视图的无障碍委托设置为与新委托关联。当开发人员设置 AccessibilityComponentType
时,原生代码根据传入的组件创建一个新的委托,并将视图设置为具有该无障碍委托。
所做的更改
对于我们的新属性,我们希望创建这两个属性的超集。我们决定让新属性主要以现有属性 accessibilityTraits
为模型,因为 accessibilityTraits
具有明显更多的值。Android 对于这些特性的功能将通过修改无障碍委托进行 Polyfill。
iOS 上的 accessibilityTraits
可以设置为 17 个 UIAccessibilityTraits
值。但是,我们没有将所有这些值都包含在新属性的可能值中。这是因为设置其中一些特性的效果实际上不是很清楚,而且其中许多值几乎从未使用过。
UIAccessibilityTraits 的值通常有两种用途。它们要么描述 UI 元素的角色,要么描述 UI 元素所处的状态。我们观察到的以前属性的大多数用法通常使用一个表示角色的值,并将其与“状态选中”、“状态禁用”或两者结合。因此,我们决定创建两个新的无障碍属性:accessibilityRole
和 accessibilityState
。
accessibilityRole
新属性accessibilityRole
用于告诉Talkback或Voiceover UI元素的角色。此新属性可以取以下值之一
无
按钮
链接
搜索
图片
键盘键
文本
可调整
标题
总结
图片按钮
此属性只允许传入一个值,因为UI元素通常逻辑上不会承担其中多个角色。例外是图片和按钮,因此我们添加了一个组合两者的角色“图片按钮”。
辅助功能状态
新属性accessibilityStates
用于告诉Talkback或Voiceover UI元素的状态。此属性接受一个包含以下一个或两个值的数组
已选中
已禁用
解决方案二:添加辅助功能提示
为此,我们添加了一个新属性:accessibilityHint
。设置此属性将允许Talkback或Voiceover向用户朗读提示。
accessibilityHint
此属性以字符串形式接收要读取的辅助功能提示。
在 iOS 上,设置此属性将设置视图上相应的原生属性 AccessibilityHint。如果 iPhone 中开启了辅助功能提示,则 Voiceover 将朗读该提示。
在 Android 上,设置此属性会将提示的值附加到无障碍标签的末尾。这种实现方式的优点是它模仿了 iOS 上提示的行为,但缺点是这些提示不能像 iOS 上那样在 Android 的设置中关闭。
我们在Android上做出这个决定的原因是,通常情况下,辅助功能提示与特定动作(例如,点击)相关联,我们希望在不同平台之间保持行为一致。
问题三的解决方案
accessibilityIgnoresInvertColors
我们已将 Apple 的 API `AccessibilityIgnoresInvertColors` 暴露给 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很有用!并请继续让应用程序无障碍!#包容