随着技术的进步和移动应用在日常生活中的重要性日益增加,创建无障碍应用程序的必要性也越来越重要。
React Native 有限的无障碍功能 API 一直是开发人员的巨大痛点,因此我们对无障碍功能 API 进行了一些更新,使其更容易创建包容性的移动应用程序。
现有 API 的问题
问题一:两个完全不同但又相似的属性 - accessibilityComponentType (Android) 和 accessibilityTraits (iOS)
accessibilityComponentType
和 accessibilityTraits
是两个属性,用于告诉 Android 上的 TalkBack 和 iOS 上的 VoiceOver 用户正在与哪种 UI 元素进行交互。这两个属性最大的两个问题是
- 它们是两个不同的属性,具有不同的使用方法,但具有相同的目的。 在之前的 API 中,这些是两个独立的属性(每个平台一个),这不仅不方便,而且对许多开发人员来说也很困惑。iOS 上的
accessibilityTraits
允许 17 个不同的值,而 Android 上的 accessibilityComponentType
仅允许 4 个值。此外,这些值在很大程度上没有重叠。甚至这两个属性的输入类型也不同。accessibilityTraits
允许传入 traits 数组或单个 trait,而 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 属性传递到原生的 17 个 traits 中的每一个都映射到 Objective-C 中的 UIAccessibilityTraits
元素。Traits 各自用一个长整型表示,并且每个设置的 trait 都被 ORed 在一起。
但是,在 Android 上,AccessibilityComponentType
是 React Native 提出的一个概念,并且不直接映射到 Android 中的任何属性。无障碍功能由无障碍功能委托处理。每个视图都有一个默认的无障碍功能委托。如果要自定义任何无障碍功能操作,则必须创建一个新的无障碍功能委托,覆盖要自定义的特定方法,然后将要处理的视图的无障碍功能委托设置为与新委托关联。当开发人员设置 AccessibilityComponentType
时,原生代码会基于传入的组件创建一个新的委托,并将视图设置为具有该无障碍功能委托。
所做的更改
对于我们的新属性,我们希望创建一个这两个属性的超集。我们决定将新属性主要仿照现有属性 accessibilityTraits
建模,因为 accessibilityTraits
具有明显更多的值。Android 上这些 traits 的功能将通过修改无障碍功能委托来进行 polyfill。
accessibilityTraits
在 iOS 上可以设置为 17 个 UIAccessibilityTraits 值。但是,我们没有将所有这些值都包含为我们新属性的可能值。这是因为设置其中一些 traits 的效果实际上不是很清楚,并且其中许多值实际上从未使用过。
UIAccessibilityTraits 设置的值通常具有两个目的之一。它们要么描述 UI 元素具有的角色,要么描述 UI 元素所处的状态。我们观察到以前属性的大多数用途通常使用一个代表角色的值,并将其与“state selected”、“state disabled”或两者结合使用。因此,我们决定创建两个新的无障碍功能属性:accessibilityRole
和 accessibilityState
。
accessibilityRole
新属性 accessibilityRole
用于告诉 Talkback 或 Voiceover UI 元素的角色。此新属性可以采用以下值之一
无
按钮
链接
搜索
图像
键盘按键
文本
可调节
标题
摘要
图像按钮
此属性仅允许传入一个值,因为 UI 元素通常在逻辑上不会承担多个角色。例外情况是图像和按钮,因此我们添加了一个角色 imagebutton,它是两者的组合。
accessibilityStates
新属性 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. 使用手动 codemod
对于使用了 AccessibilityTraits
但没有 AccessibilityRole
的相应值的情况,以及将多个 traits 传递到 AccessibilityTraits
的情况,必须进行手动 codemod。
一般来说,
accessibilityTraits= {[“button”, “selected”]}
将手动替换为
accessibilityRole=“button”
accessibilityStates={[“selected”]}
这些属性已在 Facebook 的代码库中使用。Facebook 的 codemod 非常简单。jscodeshift 脚本修复了我们大约一半的实例,另一半是手动修复的。总的来说,整个过程不到几个小时。
希望您会发现更新后的 API 很有用!并请继续制作无障碍应用!#包容性