关于支持 VoiceOver

Voice Over 是苹果出的为方便视力障碍人士使用手机的功能,打开后就能够把屏幕上的内容用语音读出来。一般开发的 app 不多考虑到这个功能,也没有作适配。可是 UILabelUIButton 自己是支持 Voice Over的,不用作适配均可以自动读出来。可是自定义 View 这样的仍是须要作一下适配会体验比较好一点。html

1、适配

适配 VoiceOver 最重要的几个方法就是node

@property(nonatomic) BOOL isAccessibilityElement;bash

@property(nonatomic, copy) NSString *accessibilityLabel;app

@property(nonatomic, copy) NSString *accessibilityHint;post

@property(nonatomic) UIAccessibilityTraits accessibilityTraits;atom

@property(nonatomic, copy) NSString *accessibilityValue;spa

accessibilityLabel(标签)一个简单的词或短语,它简洁明了地描述控件或者视图,可是不能识别元素类型,UIAccessibilityElement必需要有这个属性。例如“添加”、“播放”。.net

accessibilityHint(提示)一个简单的词或短语,描述发生在元素上动做的结果。例如“添加标题”或者“打开购物列表”。code

accessibilityValue(值)不是由标签订义的元素时的当前值。仅当元素的内容是可改变而且不能使用label描述时,一个无障碍元素才须要为其赋值。例如,一个进度条的标签能够是”播放进度”,可是它当前的值是“50%”。htm

accessibilityTraits这个element的类型以及状态,就是经过traits来表征这个Element的特质,数据类型是一个枚举类型,能够经过按位或的方式合并多个特性。

VoiceOver会把这几个属性链接起来,朗读顺序为label→value(可选)→traits→hint。但须要注意的是,当某个View的是AccessibilityElement的时候 ,其subviews都会被屏蔽掉,若是想要都读出来,只能改变他们的层次结构,并都设置isAccessibilityElement为YES。这个特性仍是挺有用的,好比一个View中有多个Label,那么每个下面的Label单独访问可能意义不大,那么就能够将这个View设置成能够访问的,而后将其accessibilityLabel设置为全部子Label的 accessibilityLabel的合并值。

这几个属性都是能够赋值也能够重载。不过推荐重载,这样看起来更清晰。 并且对于accessibilityLabel 的重载也有下面的好处:

一、这个是在 Voice Over聚焦到控件的时候才去调用,那么若是重载的话,就是相似于懒加载这种了,用到的时候才去初始化。

二、对于自定义 View,包括 cell,会有不少状态,显示的内容都是根据状态来的,那么这时候重载的话,就能够把这部分代码写在一块儿,和 正常的代码区分开。

2、Texture 的适配

关于 Texture 的自定义 view,能够指定 isAccessibilityContainer == YES,指定这个属性为 YES以后,Texture 能够自动把这个 view 下面支持 Voice Over的子控件给组合起来,造成一个总体,而且子控件有 button 的时候,实现了 一个手指上下轻扫 响应自定义事件,分红方便。

可是有个问题就是 Texture 自己没有处理 控件的 accessibilityElementsHidden 属性。并且也没有判断子控件的状态是显示仍是隐藏,只是 遍历了子控件,能读的就给读出来。因此 Texture的适配就是 判断隐藏的子控件,不能用隐藏方法,只能是直接不添加,不调用addSubnode

3、播放自定义语音,自动读出Toast内容

直接上代码:

UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, message);
复制代码

利用这个功能,能够读出 Toast的内容,目前toast控件,大部分都是直接 addSubview 到UIWindow上的,这样实现不会自动聚焦,直到自动消失以后也读不出来。能够用这个方法来读出 TOAST的 内容,或者其余的提示。

可是有个主意的地方就是若是当前正在播报内容,这个时候直接调用时读不出来的,因此加了个延迟

hud.isAccessibilityElement = YES;
hud.accessibilityLabel = message;
hud.accessibilityTraits = UIAccessibilityTraitStaticText;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, message);
});
复制代码

4、自动聚焦

直接上代码

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, VIEW);
复制代码

5、自定义事件

UIAccessibilityCustomAction,用这个类来初始化来实现自定义的事件,自定义事件在 单个手指上下轻扫后 出来,若是有多个的话,继续上下轻扫来切换,而后再单个手指 双击来响应该事件(例如 UITableViewCell 的删除事件)。

初始化后,能够绑定到控件的

@property (nullable, nonatomic, strong) NSArray <UIAccessibilityCustomAction *> *accessibilityCustomActions NS_AVAILABLE_IOS(8_0);
复制代码

属性上。这个属性是 NSObject的扩展。因此 UIKit 的控件应该都支持。

这个属性针对 Cell的适配很是有用。例如 电商类的 app,一个 cell 也许是一个商品,这时候能够把整个 cell 设置 isAccessibilityElement,指定为 AccessibilityElement,成为一个总体,而后组合商品名字,价格属性等 来读出,而后 利用 accessibilityCustomActions 来直接加入购物车。

6、提示框 Alert & Actionsheet

系统的 UIAlert 和 UIActionSheet 固然系统作了自动适配,没有问题。问题在于 自定义的 Alert 和 ActionSheet。

一、若是是 只用 用 addSubviewkeyWindow的话,那么 提示框出来以后压根就不会自动聚焦读出,只能手指点上去才会读出,这个对盲人不现实。

二、若是用了本身生成的一个 window,而后把 alert 添加到这个 window 上的话,那么会有自动聚焦,再显示弹出框的时候能够自动读出,可是当手指不当心碰到空白区域后,焦点就会跑到背景上下面正常显示的 view,会读出背景后面的内容。

为了解决这个问题,那么对于自定义的 Alert 都改成了 利用 presentViewController的方式来实现。能够自动读出,也不会点到空白区域就失去焦点。见这里

参考:

blog.csdn.net/heyc861221/…

blog.csdn.net/u010850094/…

blog.csdn.net/heyc861221/…

www.logcg.com/archives/23…

相关文章
相关标签/搜索