苹果读屏技术–VoiceOver
一、系统VoiceOver使用简介
iPhone上开启VoiceOver功能后,就可以通过手势来操作当前界面中的所有的AccessibilityElement(被VoiceOver访问的UI元素),当点击一个AccessibilityElement,如果当前AccessibilityElement是label时,VoiceOver会将AccessibilityElement的信息读出来。
二、概念
AccessibilityElement
指可以被VoiceOver访问的UI元素,UIKit中的控件基本都支持VoiceOver,除了UIView,不过也可以通过设置UIView的isAccessibilityElement属性来控制某个View是否是AccessibilityElement,在UIKit的控件中,像UILabel,UIButton这些控件的isAccessibilityElement属性默认就是YES,UIView这个属性默认是NO。
三、开发支持VoiceOver
######1、UIAccessibility及相关类
-
UIAccessibility(Informal Protocol):实现UIAccessibility协议的对象报告其可访问性状态(即是否可访问),并提供有关其自身的描述性信息。 默认情况下,标准的UIKit控件和视图实现了UIAccessibility协议,障碍类型的app可以将这些控件展现给视力障碍用户。但是自定义的内容需要重写UIAccessibility ,根据需要支持某些设置即可。例如,我们的自定义UIImageView 子类可能需要覆盖accessibilityLabel,但它不需要覆盖accessibilityFrame。
-
UIAccessibilityContainer(Informal Protocol):该协议一般用于UIView的子类,可以让它所包含的一些子UI作为单独的元素被访问到。当一个视图所包含的子对象并不是UIView的子类,而又需要被访问到的时候,这个协议就非常有用。
-
UIAccessibilityElement(Class):这个类默认实现了UIAccessibility协议,可以为一个不能被自动访问到的对象(例如非UIView的子类)创建一个该类的实例,从而让它可以被访问到
2、正确使用UIAccessibility
-
标准的UIKit controls和views都是自动无障碍的,所以只需要确保它们默认提供的无障碍信息是否准确。
-
自定义的view或控件,需要自己实现它的无障碍配置,这种情况又可以分为以下两种:
-
an individual view:自定义view里面不包含任何子元素
//方式一:直接给isAccessibilityElement属性赋值,标识为无障碍原色 view.isAccessibilityElement = YES // 方式二:实现UIAccessibilityProtocol协议中的方法 - (BOOL)isAccessibilityElement { return YES; }
-
a container view:自定义view里面包含其他子元素,那么这些子元素都需要做无障碍配置,容器视图本身不需要无障碍配置。
//假定所有子元素都没有默认实现UIAccessibility协议,此时需要用到UIAccessibilityElement @implementation ContainerView - (NSArray *)accessibleElements { if ( _accessibleElements != nil ) { return _accessibleElements; } _accessibleElements = [[NSMutableArray alloc] init]; // 每一个子元素都是一个UIAccessibilityElement,将他们全都添加到_accessibleElements中 UIAccessibilityElement *element1 = [[[UIAccessibilityElement alloc] initWithAccessibilityContainer:self] autorelease]; [_accessibleElements addObject:element1]; UIAccessibilityElement *element2 = [[[UIAccessibilityElement alloc] initWithAccessibilityContainer:self] autorelease]; [_accessibleElements addObject:element2]; return _accessibleElements; } // 这个ContainerView是不支持Accessibility的 - (BOOL)isAccessibilityElement { return NO; } // UIAccessibilityContainer协议方法 - (NSInteger)accessibilityElementCount { return [[self accessibleElements] count]; } - (id)accessibilityElementAtIndex:(NSInteger)index { return [[self accessibleElements] objectAtIndex:index]; } - (NSInteger)indexOfAccessibilityElement:(id)element { return [[self accessibleElements] indexOfObject:element]; } @end
-
3、Accessibility使用恰当合理
(1)确保Accessibility各属性的准确可靠
保证accessibilityLabel、accessibilityHint、accessibilityValue、accessibilityTraits设置的值,表达的信息准确可靠,我们分别看看这些属性
-
accessibilityLabel(标签)用于设置一个简单的词或短语描述控件或者视图,但是不能识别元素类型,例如“添加”、“播放”。
-
accessibilityHint(提示)用于设置一个简单的词或短语,描述发生在元素上动作的结果。例如“添加标题”或者“打开列表”。
-
accessibilityValue(值)指一个UI元素的内容,仅当元素的内容是可改变并且不能使用label描述时,一个无障碍元素才需要为其赋值。例如,一个进度条的标签可以是”播放进度”,但是它当前的值是“50%”。
-
accessibilityFrame(区域)定义辅助功能的区域和UI元素的位置,
-
accessibilityTraits,辅助功能特征,表征这个Element的特质,数据类型是一个枚举类型,可以通过按位或的方式合并多个特性,配置的traits的值,也会以语音的形式念出,例如设置
UIAccessibilityTraitSelected | UIAccessibilityTraitImage | UIAccessibilityTraitButton
会变成“已选定,图片,按钮”UIAccessibilityTraits UIAccessibilityTraitNone;//该无障碍元素无特性。
UIAccessibilityTraits UIAccessibilityTraitButton;//该无障碍元素应该被当作一个按钮
UIAccessibilityTraits UIAccessibilityTraitLink; //该无障碍元素应该被当作一个链接
UIAccessibilityTraits UIAccessibilityTraitSearchField; //该无障碍元素为搜索区域
UIAccessibilityTraits UIAccessibilityTraitImage; //该无障碍元素应该被当作一个链接,该特性可以与按钮或链接特性组合使用
UIAccessibilityTraits UIAccessibilityTraitSelected; //该无障碍元素当前已被选定。
使用该特性描述一个无障碍元素的特征,例如,在一个分段控件中,呈现已选定表行或已选定段UIAccessibilityTraits UIAccessibilityTraitPlaysSound; //该无障碍元素被激活时播放自己的声音
UIAccessibilityTraits UIAccessibilityTraitKeyboardKey; //该无障碍元素的行为键盘键
UIAccessibilityTraits UIAccessibilityTraitStaticText; //该无障碍元素应该被当作不能改变的静态文本
UIAccessibilityTraits UIAccessibilityTraitSummaryElement; //当应用启动时,该无障碍元素提供摘要信息。使用该属性描述一个无障碍元素的特征,该元素提供当前情况、设置或状态的摘要,例如天气应用中的当前气温
UIAccessibilityTraits UIAccessibilityTraitNotEnabled; //该无障碍元素不可用且不能响应用户交互
UIAccessibilityTraits UIAccessibilityTraitUpdatesFrequently; //该无障碍元素频繁更新其标签或值。
使用该特性描述一个无障碍元素的特征,该元素频繁更新其标签或值发送更新通知。当想要避免辅助应用处理不断的通知时,和当需要更新信息而轮询改变时,包含该特性。例如,开发者可以使用该属性描述秒表朗读的特征UIAccessibilityTraits UIAccessibilityTraitStartsMediaSession; //当该无障碍元素被激活时,启动一个媒体对话。
使用该特性关闭辅助应用的音频输出,例如VoiceOver。在媒体会话期间,媒体会话不应该被打断。例如,当用户录制音频的时候,开发者可以使用该属性静音VoiceOverUIAccessibilityTraits UIAccessibilityTraitAdjustable; //该无障碍元素的值在一定范围内允许持续调整。
使用该属性描述一个无障碍元素的特征,用户可以使用持续的行为调整该元素,例如滑块或选择器视图。如果为一个无障碍元素指定了该特性,开发者同时应该在UIAccessibilityAction协议中实现accessibilityIncrement和accessibility Decrement方法UIAccessibilityTraits UIAccessibilityTraitAllowsDirectInteraction; //该无障碍元素允许VoiceOver用户直接触摸交互。使用该特性描述一个无障碍元素的特征,该元素呈现的对象用户可以直接交互,例如呈现钢琴键盘的视图
UIAccessibilityTraits UIAccessibilityTraitCausesPageTurn; //该无障碍元素应该引起自动翻页,当VoiceOver阅读完成当页的文本时。使用该特性描述一个无障碍元素的特征,该元素在一系列页面内容中呈现一个页面,例如呈现一本书中的一页。当VoiceOver阅读完成当前页面的内容,调用具有UIAccessibilityScrollDirectionNext属性的accessibilityScroll方法滚动到下一内容页。如果VoiceOver检测到当前页面与先前的页面无差异,停止滚动
UIAccessibilityTraits UIAccessibilityTraitHeader;//该无障碍元素是一个将内容划分为章节的标题,例如导航栏的标题
-
isAccessibilityElement 设置是否支持盲人模式,isAccessibilityElement默认是false,UIKit默认打开,但是UIImageView需要单独打开.
-
accessibilityElementHidden 不在读取该元素.isAccessbilityElement为NO值只读取label,如果将accessibilityElementHidden设为YES,lable也不再读取.
(2)相关事件Actions
-
Activate 单指轻点两次. 表示激活控件,如按钮点击
-
Escape. 单指 Z-shaped 手势一般用于退出模态界面或者返回导航的上一页界面
-
Magic Tap. 双指轻点两次触发 most-intended action.
-
Three-Finger Scroll. 触发水平滚动,如UIScrollView
-
Increment. 单指向上滑动,需要设置accessibilityTraits为UIAccessibilityTraitAdjustable,否则对应的方法不会被调用
-
Decrement. 单指向下滑动,需要设置accessibilityTraits为UIAccessibilityTraitAdjustable,否则对应的方法不会被调用
(3)主动设置
-
设置焦点元素
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, element)
-
直接读出一段文字
void UIAccessibilityPostNotification(UIAccessibilityNotifications notification, __nullable id argument) 例如 UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @"read me");
-
是否开启了盲人模式
BOOL UIAccessibilityIsVoiceOverRunning(void)
-
监听盲人模式状态改变
通知名称为:UIAccessibilityVoiceOverStatusChanged
读屏官方文档
https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/iPhoneAccessibility/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008785-CH1-SW1
Accessibility Inspector介绍
https://www.raywenderlich.com/6827616-ios-accessibility-getting-started
http://www.cocoachina.com/articles/24250
优秀的相关博客
https://blog.csdn.net/heyc861221/article/details/80125550
https://zhuanlan.zhihu.com/p/22776897