无障碍功能 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 元素只有“button”、“radiobutton_checked”和“radiobutton_unchecked”。
问题二:不存在的无障碍功能提示:
无障碍功能提示帮助使用 TalkBack 或 VoiceOver 的用户了解当他们在无障碍功能元素上执行操作时会发生什么,而这仅凭无障碍功能标签是不明显的。这些提示可以在设置面板中打开和关闭。以前,React Native 的 API 完全不支持无障碍功能提示。
问题三:忽略反转颜色:
一些视力障碍用户在其手机上使用反转颜色以获得更高的屏幕对比度。Apple 为 iOS 提供了一个 API,允许开发者忽略某些视图。这样,当用户开启反转颜色设置时,图像和视频不会失真。React Native 目前不支持此 API。
新 API 的设计
解决方案一:合并 accessibilityComponentType (Android) 和 accessibilityTraits (iOS)
为了解决 accessibilityComponentType
和 accessibilityTraits
之间的混淆,我们决定将它们合并为一个属性。这很有意义,因为它们在技术上具有相同的功能,并且通过合并它们,开发者在构建无障碍功能时不再需要担心特定于平台的复杂性。
背景
在 iOS 上,UIAccessibilityTraits
是一个可以设置在任何 NSObject 上的属性。通过 javascript 属性传递给 native 的 17 个特征中的每一个都映射到 Objective-C 中的 UIAccessibilityTraits
元素。特征均由一个长整型表示,并且每个设置的特征都通过 OR 运算组合在一起。
然而,在 Android 上,AccessibilityComponentType
是 React Native 提出的一个概念,并不直接映射到 Android 中的任何属性。无障碍功能由无障碍功能委托处理。每个视图都有一个默认的无障碍功能委托。如果您想自定义任何无障碍功能操作,您必须创建一个新的无障碍功能委托,覆盖您想要自定义的特定方法,然后将您正在处理的视图的无障碍功能委托设置为与新的委托关联。当开发者设置 AccessibilityComponentType
时,native 代码会基于传入的组件创建一个新的委托,并将视图设置为具有该无障碍功能委托。
所做的更改
对于我们的新属性,我们希望创建两个属性的超集。我们决定将新属性主要模仿现有属性 accessibilityTraits
建模,因为 accessibilityTraits
具有明显更多的值。Android 上这些特征的功能将通过修改无障碍功能委托来 polyfill。
accessibilityTraits
在 iOS 上可以设置为 17 个 UIAccessibilityTraits 值。但是,我们并没有将所有这些都包含为我们新属性的可能值。这是因为设置其中一些特征的效果实际上不是很为人所知,并且其中许多值实际上从未使用过。
UIAccessibilityTraits 值通常用于两种目的之一。它们要么描述 UI 元素具有的角色,要么描述 UI 元素所处的状态。我们观察到以前属性的大多数用法通常使用一个代表角色的值,并将其与“state selected”、“state disabled”或两者结合使用。因此,我们决定创建两个新的无障碍功能属性:accessibilityRole
和 accessibilityState
。
accessibilityRole
新属性 accessibilityRole
用于告诉 Talkback 或 Voiceover UI 元素的角色。这个新属性可以采用以下值之一
none
button
link
search
image
keyboardkey
text
adjustable
header
summary
imagebutton
此属性仅允许传入一个值,因为 UI 元素通常在逻辑上不会承担多个角色。例外情况是 image 和 button,因此我们添加了一个 role imagebutton,它是两者的组合。
accessibilityStates
新属性 accessibilityStates
用于告诉 Talkback 或 Voiceover UI 元素所处的状态。此属性采用一个数组,其中包含以下一个或两个值
selected
disabled
解决方案二:添加无障碍功能提示
为此,我们添加了一个新属性 accessibilityHint
。设置此属性将允许 Talkback 或 Voiceover 向用户朗读提示。
accessibilityHint
此属性以字符串形式接收要读取的无障碍功能提示。
在 iOS 上,设置此属性将在视图上设置相应的 native 属性 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. 使用手动 codemod
对于使用 AccessibilityTraits
但没有 AccessibilityRole
的对应值的情况,以及将多个特征传递到 AccessibilityTraits
的情况,必须手动完成 codemod。
一般来说,
accessibilityTraits= {[“button”, “selected”]}
将手动替换为
accessibilityRole=“button”
accessibilityStates={[“selected”]}
这些属性已经在 Facebook 的代码库中使用。Facebook 的 codemod 非常简单。jscodeshift 脚本修复了我们大约一半的实例,另一半是手动修复的。总的来说,整个过程花费了不到几个小时。
希望您会发现更新后的 API 很有用!并请继续制作无障碍应用!#包容性