【译】让你的应用支持旁白(iOS无障碍化官方文档)

3,416 阅读7分钟

本文将介绍如何通过添加”旁白”(VoiceOver)能力让你的iOS App对盲人等视障人士更加友好。

概要

“旁白”是一种屏幕阅读能力,它使得人们可以在不看屏幕的情况下浏览设备的界面。盲人用户在使用他们的iOS设备时依赖”旁白“提供听觉反馈,但“旁白”不仅仅是给盲人群体的。例如,一些晕车的人在乘车时也可能会选择打开“旁白”功能。“旁白”功能为各种人士提供便利,而盲人们在使用设备时更加依赖它。

使用Xcode或者纯代码的方式,只需要几步你就可以使你的APP适配“旁白”功能。通过无障碍化,你的APP将走进一个广阔的市场,同时对任何用户来讲都会更加易用。

Two iPhones with VoiceOver turned on. The phone on the left has the camera app open and the VoiceOver cursor is highlighting the timer. The phone on the right shows a contact in the phone app for Maria Ruiz. The call home button is highlighted by the VoiceOver cursor.

开启“旁白”功能测试你的APP

为了测试APP的无障碍性,让我们打开“旁白”功能浏览一下界面吧。通过在“旁白”功能下使用你的APP,你将能够对它的无障碍性有个基本认知。首先,打开 设置 > 通用 > 辅助功能 > 旁白,打开“旁白”功能。然后,打开你的app,在任何你想测试"旁白"功能的地方使用特定手势操作。

这种测试也会反映哪些元素在"旁白"中是可访问的,哪些是不能的。同时可以告诉你"旁白"的浏览顺序是否清晰且合乎逻辑。持续关注不支持无障碍的元素并记录一个清单用于添加更好的无障碍支持能力吧。

使用"旁白"浏览你的app

使用"旁白"测试app,需要你使用"旁白"功能的一组特定手势。

这里有五种关键的常用手势:

  • 左划或右划将跳转到下一个或前一个元素
  • 一个手指双击屏幕相当于点选当前元素
  • 双指单机屏幕可以停止或恢复语音
  • 双指上划可以读出屏幕上的所有内容
  • 三指三击屏幕可以关闭或打开"幕帘屏"

想要了解更多手势,可以参考用户指南

为了完整还原盲人用户的体验,可以在"幕帘屏"下测试你的应用。从名字也可以大概看出来,"幕帘屏"会使整个屏幕变黑。打开"幕帘屏"后,你仍然可以使用"旁白"手势,但你不能看到屏幕上的元素。

现在你可以打开"旁白"并且知道如何浏览你的app,你已经可以测试你的app了。

确定常见的可访问性问题

为了测试你的app,检查你是否能够访问每一个元素并且这些元素的顺序是否是你期望的。记录下来每个元素是否可以访问。同时,关注那些在"旁白"功能下难以使用的功能。例如,返回app初始页面,或者向其它应用或用户分享内容,如何才能使用"旁白"功能做到呢?

当你测试你的app时,有一些常见的问题需要关注:

  • 为你的app的元素添加可访问信息。 "旁白"不能默认识别自定义UI元素,你需要给这些元素添加额外的可访问信息。
  • __为元素分组来让”旁白“能够以正确的顺序遍历它们。__”旁白“默认是从前往后读的,如果你希望”旁白“以不同的顺序遍历元素,使用元素分组来优化。这对你的app是有意义的。
  • __添加描述性的文本给”旁白“来读。__一个依赖视觉的UI看起来会很棒,但是对”旁白“用户来说可能是无法使用得。例如,”旁白“不会检测到一个确认按钮在选中时从灰色变成了绿色。不作处理的话,”旁白“可能只会描述元素本身,而不会反映元素的当前状态。确保”旁白“能够读出按钮是否被选中。

现在你知道哪些地方需要优化了,给你的app添加更好的”旁白“支持吧。

优化你的App的无障碍性

对那些无法用”旁白“访问的元素,首先来优化它们的标签(labels)和提示(hints)。

  • 属性accessibilityLabel提供了一段描述文本,当用户选中元素时,"旁白"会读出这段文字。
  • 属性accessibilityHint为选中的元素提供额外的提示信息。

Labels是非常重要的,因为它们提供了"旁白"可读的文本。一个好的label应该简洁但包含足够的信息。注意一下,UILabel和accessibilityLabel是两回事。默认地,"旁白"会读出标准UIKit控件的文本内容,比如UILabel和UIButton。但是这些控件也可以单独设置accessibilityLabel来添加更细节的信息。

hints不是总是必要的,需要结合具体场景考虑。在某些场景下,label已经提供了足够的信息。如果你觉得label里的内容太多了,可以放一些到hint里面。

为了确保用户能够理解界面的意图,你看你需要手动设置一些label。label和hint可以通过xcode的Identity Inspector设置也可以在代码里手动设置。

通过Identity Inspector添加Label和Hint

当使用标准UIKit控件时,可以在Xcode中Identity Inspector的Accessibility面板设置Label和Hint。为了提升可访问性,通过勾选Accessibility使当前元素可访问。例如,一个音乐App的播放按钮应当包含图二中的label和hint。

A screenshot from Xcode, showing the Accessibility pane of the Identity inspector. This pane includes a checkbox to enable accessibility, and three text fields in which you enter text for an object’s Label, Hint, and an Identifier. In this screenshot, the Accessibility checkbox is Enabled. The Label field says “Play song,” and the Hint field says “Play the selected song.” The Identifier field is blank.

图二:Identity Inspector中的Accessibility面板

通过代码添加Label和Hint

很多时候通过Xcode设置Label和Hint是不够的。例如,当你使用一个自定义UI组件的时候,"旁白"不会自动读出。当你在label里包含了一个变量的时候,也会有类似的问题。在这些情况下,你只能在代码里设置Label和Hint。首先需要确认,这个元素是否是无障碍化的,然后添加合适的label和hint。

为了使元素可以被"旁白"访问到,需要把它定义为一个可访问元素。

score.isAccessibilityElement = true

一个元素的label在整个生命周期中可能会变化。例如,一个用于计算游戏得分的计数器,你希望分数变动时label的内容也会变化。你可以通过如下代码设置label和hint:

score.accessibilityLabel = "score: \(currentScore)"
score.accessibilityHint = "Your current score" 

简化无障碍信息

"旁白"使用系统语言的方向来决定遍历界面元素的方向。例如,在英语国家,"旁白"从左向右遍历,而在阿拉伯语和波斯语就是从右往左读的。如果你在UI上纵向地堆叠label,或者是在一个table里展示文本,"旁白"可能不会以正确的顺序遍历这些label。你可以在代码里给可访问元素分组来确保"旁白"的阅读顺序符合预期。例如,假设你创建了一个app,从上到下分别是Name和Email的标题和内容,如图三。

由于它们在界面上的顺序,"旁白"不会把这些元素一起读出来。为了保证"旁白"读出的内容是明确的,需要让这些元素被分为一组。

Two side-by-side diagrams, demonstrating how VoiceOver reads ungrouped and grouped labels. On the left, there are two pairs of ungrouped labels—one pair on the left and another pair on the right—used to depict a person’s name and email address. When ungrouped, VoiceOver reads the labels in a top-left, top-right, bottom-left, and bottom-right sequence. On the right, the top- and bottom-left labels are in one group, and the top- and bottom-right labels are in a second group. When grouped, VoiceOver still reads left-to-right and top-to-bottom, but this time it reads the first group (at left) before reading the second group (at right) from top-to-bottom.

图三:未分组和分组情况下,"旁白"如何遍历元素的例子

左图中,有四个Label,"旁白"从前往后读,在这个例子里,是从左往右。由于每个元素对"旁白"来说都是可访问的,这样的用户体验不是很好。而右图中,"旁白"以符合预期的顺序阅读分好组的Label,界面就很清晰。

要用代码给label分组,首先创建一个UIAccessibilityElement,然后给已经分好组的元素添加你想要的信息。例如,像下面这样给label分组:

var elements = [UIAccessibilityElement]()
let groupedElement = UIAccessibilityElement(accessibilityContainer: self)
groupedElement.accessibilityLabel = "\(nameTitle.text!), \(nameValue.text!)"
groupedElement.accessibilityFrameInContainerSpace = nameTitle.frame.union(nameValue.frame)
elements.append(groupedElement)

为每个元素添加无障碍标签并对元素进行分组,能够让"旁白"用户更好地使用你的app。


译者注,

  1. 个人理解,最后这个分组的例子,可能是为了不破坏原有页面视图树所以塞了个groupedElement进来。我们通常的做法是把"Name:"和"Maria Ruiz"两个label塞到一个UIView里面去,对这个UIView设isAccessibilityElement和accessibilityLabel两个属性。
  2. 无障碍化比较有社会意义,经济价值可能一般,所以受到的关注也不太多。官方迭代过好几份文档,这个是目前最新的,搜了一下好像没有中文版,简单翻译一下吧,虽然翻得比较烂,但是也算是有一点意义嘛。