本文旨在系统性的介绍iOS的Accessibility旁白功能,什么是Accessibility?用户如何操作使用?Accessibility相关API如何使用?Accessibility的代码实践、解决实际问题?
一、什么是Accessibility?如何使用?
什么是Accessibility呢?
简单来说,就是无障碍化使用,这里的“无障碍”面向的群体是视障人士。
一般来说,在App的开发过程中,我们都会关注产品的易用性、考虑不同用户的需求。但是,我们的关注点往往在于身体健全的用户,而对于视障人士,其实也是潜在的用户群体,当我们需要服务好这类用户群体时,就需要做好App对于Accessibility的支持了。
对于目前的移动端,无论是Android还是iOS,其实系统已经为我们提供了Accessibility的接口。拿iOS来说,苹果已经在UIKit中集成了UIAccessibility,当我们在使用UI控件时,都可以设置Accessibility相关的属性,进而支持功能。
说了这么多,我们先来看看如何在iPhone上开启Accessibility功能。
进入“设置(Settings)”->"通用(General)"->"辅助功能(Accessibility)"->"旁白(VoiceOver)",开启旁白的开关
当我们开启成功后,屏幕上就会出现黑色边框,并且手机会帮助我们读出边框选中的内容。
二、Accessibility模式下的用户操作
如上所述,当我们开启了Accessibility的旁白功能后,整个用户操作的模式也相应的发生了改变,更加的符合视障人士的习惯。同时,我们也可以闭上眼睛,对手机App进行操作,去感受怎样的代码实现对于视障人士更加的友好。
在此,针对这种模式下的手势操作代表的功能做一个简述:
1.单击手势:
黑色边框会移动并聚焦到单击的界面元素上,同时读出当前选中部分所代表的功能、内容。此时的单击手势和正常情况下不同,并不会触发代码层面的功能的响应。
2.双击手势:
如果当前黑色边框聚焦的界面元素是一个Button或者关联了一些点击响应方法等,则此时会触发相应的方法,等同于正常情况下的单击操作。
3.单指滑动:
会将黑色边框移动聚焦到下一个界面元素上(向左滑动会聚焦到上一个元素上)
4.三指滑动:
一般会触发tableview、scrollview等的滑动功能,进而滑动页面
5.回到主屏幕(无home键手机):
手指从底部向上滑动且不离开屏幕,直到感知到震动后,松开手指,就会回到主屏幕
在这里主要描述了使用概率较高的集中操作方式。总之,在这种模式下的手势操作要更加复杂一点,但是对于视障人士更加友好,提升了操作的准确性。
三、代码如何更好的支持Accessibility呢?
如开头所说,iOS已经帮我们在UIKit中集成了Accessibility的一些功能。也就是说,在我们开发完一个项目后,暂未添加任何Accessibility相关代码的情况下,我们的App已经支持了一些旁白功能,能够自动聚焦并且读出Label的内容等。
但是,仅仅是这样还是不够的,对于视障人士来说可用性还是比较差的,所以我们需要通过对Accessibility的一些API进行操作,进而提升易用性。
所有标准的UIKit控件和UIView默认都是支持VoiceOver的,但是我们通常会自定义UI,此时VoiceOver就无法正确的为我们聚焦并读出我们想要的结果,此时就需要对Accessibility的编程接口进行修改来支持无障碍使用。
1、Accessibility常用API介绍:
isAccessibilityElement
一般来说我们在App上能够看到的界面元素都是AccessibilityElement。对于UIKit中的UIButton、UILabel等控件,它们的isAccessibilityElement默认是true,而UIView的isAccessibilityElement默认是false。系统能够自动捕捉并聚焦到AccessibilityElement是true的元素,因此,不需要聚焦到某个元素时将其isAccessibilityElement设置为false即可;需要聚焦则设置为true。accessibilityLabel
描述内容是什么。一般对于UILabel不需要进行设置,会直接读出label的内容;对于UIButton,若设置了图标的话,可能会直接读出图标的命名,因此需要对这个按钮的功能描述进行设置,例如“返回按钮”。accessibilityHint
描述详细信息(补充说明等)。一般不需要进行设置,如果读完当前元素的内容(或功能、名称)外,还需要对此进一步解释说明、提示等,则 可以针对此属性进行设置。accessibilityValue
描述值是多少。比如当前存在加载进度时,需要实时告知用户当前百分比。accessibilityTraits
描述当前元素的状态、类型等信息。例如,描述当前的元素为一个按钮则设置为“button”;当前元素高亮或已勾选则设置为“selected”,等等。根据当前的需求去设置对应的特征描述。accessibilityFrame
描述当前聚焦框的区域大小。系统会读出当前聚焦框区域中的内容。-
UIAccessibility.post()
通过这个通知方法可以完成我们特殊的一些需求。public static func post(notification: UIAccessibility.Notification, argument: Any?)
具体的用法,示例如下:
//在点击某个按钮后,我们需要将自动聚焦到title上,则可以执行以下代码 UIAccessibility.post(notification: .layoutChanged, argument: titleLabel) //如果在点击某个按钮后并且没有筛选到结果,想要提示“未搜索到结果”,则可以执行以下代码 UIAccessibility.post(notification: .layoutChanged, argument: “为搜索到结果”)
通知里的第一个参数,具体使用“layoutChanged”、“screenChanged”还是其他,根据当前的需求来看,一般来说这两个足够使用了,至于他俩的区别是啥,可以参考这篇文章。
这里只是重点说了常用的一些API及其使用方法,除此之外的系统API有兴趣的可以自行了解,苹果都有详细的注释
2、代码实践,解决实际问题:
1. 常用系统方法的基本使用:
let percent = "25%"
moreButton.accessibilityLabel = "more function"
moreButton.accessibilityTraits = .button
moreButton.accessibilityHint = "Tap to show coupon details"
moreButton.accessibilityValue = percent
//通知的用法上面已经介绍过,这里不再赘述
2. 界面元素聚焦定位的问题:
通常情况下,用户在进行界面操作后,如点击按钮、搜索等等,系统会自动帮我们重新聚焦定位、或者保持不变,但是这种表现达不到我们的预期,所以我们需要重新手动聚焦到特定的元素上。
针对这个问题,可以通过UIAccessibility.post()通知来解决。
//这里的argument传递需要聚焦的UI控件元素上。在某些特定情况下需要修改系统定位的焦点,可通过延时触发的方式执行方法
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
UIAccessibility.post(notification: .layoutChanged, argument: self.titleLabel)
}
3. 用户进行某个操作后并未触发UI控件,需要对用户进行提示:
在实际开发中,有时存在这样一个场景,用户从上一个页面返回后,会自动刷新当前的页面,但是没有特定的UI元素聚焦能够说明此变更。
针对此问题,可以通过通知来解决。在返回到当前页面时,触发通知,传递需要读出的内容
//这里的argument可以传字符串(提示的内容)。
UIAccessibility.post(notification: UIAccessibility.Notification.screenChanged, argument: "当前页面已更新")
4. 自定义UI控件,聚焦定位不准确:
当我们自定义一个UIView,并在上面添加Button、Label等控件,若不进行处理,则聚焦框会分别依次聚焦到Button、Label上。如果需要将这个View当作一个聚焦的整体,则需要将View的isAccessibilityElement属性设置为true;同时添加到View上的标准UI控件则不会被单独聚焦到了,如果有个别依然会被聚焦的则将其isAccessibilityElement设置为false。
5. 增加扩张功能:
例如,我们在针对标题类的内容时,不仅需要读出标题,还需要读出当前的标题是主标题、副标题,或者一级标题、二级标题等等。针对此类需求,可以对View、Label等增加分类方法,根据不同的需求扩展方法,对Accessibility进行设置。