介绍
1.开启voiceOver
设置->通用->辅助功能->VoiceOver
在voiceOver模式中
a.轻触一次是选中控件
b.双击激活
c.三只手指滚动视图
2.效果
当用户在选择了指定交互元素的时候,VoiceOver “说”给用户听这个元素 的信息和使用提示,而这个元素的辅助功能标签和提示告诉 VoiceOver 应该如何“说”给用户听。
比如 当你 轻触导航栏中的“返回”按钮,voiceOver会告诉你 "返回 按钮";在官网提供的VoiceOver介绍中有张图进行了介绍
3.UIAccessibility属性说明
label(标签)一个简短的本地化词或短语,此短语简洁地描述控件或者视图,但是不能识别元素类型。例如“添加”、“播放”。
traits(特性)一个或多个独立特征的组合。每个特征描述一个元素状态、行为、使用中的某一方面。例如当元素的行为如同被选中键盘上的按键,这个元素就有了Keyboard Key和Selected的组合特征。
hint(提示)一个简短的本地化短语,描述发生在元素上动作的结果。例如“添加标题”或者“打开购物列表”。
frame(框架)元素在屏幕上坐标的框架。由CGRect结构体提供,详细说明了元素的屏幕位置和大小。
value(值)不是由标签定义的元素时的当前值。例如,一个幻灯片的标签可以是”速度”,但是它当前的值是“50%”
tips:
1) UIAccessibilityElement都必须有frame和label属性
2) 仅当元素的内容是可改变并且永不被label描述时,一个无障碍元素才需要提供给值属性提供内容。例如,一个文本域包含了一个可能有Email标签的Email地址,但是它的内容取决于用户的输入,通常格式为”username@address。“value提供了一个动态更新的方式
3)voiceOver朗读的顺序 label->traits->hint
实现细节
4.UI Accessibility编程接口
UIAccessibility (informal protocol)实现UIAccessibility协议的对象可以报告无障碍状态(即他们是否是无障碍的)并且提供关于自身的描述信息。UIAccessibility协议默认由标准UIKit控件和视图都有实现,比如说某些UIView子类、UIButton,UILabel都默认实现了,voiceOver可以朗读其信息,可以自定义其属性VoiceOver朗读的信息
UIAccessibilityContainer(informal protocol)
当非UIView子类的对象被UIView视图包含时,这些元素不会自动变成无障碍元素,此时UIAccessibilityContainer协议就非常有用。
UIAccessibilityElement(class)
定义了一个对象是否能通过UIAccessibilityContainer协议返回。你可以创建UIAccessibilityElement实例来代表无法自动变为无障碍的元素,例如一个没有继承自UIView的对象,或者一个不存在的对象。
UIAccessibilityConstants.h (header file)
此头文件定义了用来描述某些特征的常量。这些常量即 可展示的无障碍元素,还有可被应用发布的通知。
5.模拟器中使用VoiceOver
在xcode编程,模拟器打开VoiceOver后,可以看到
其中Accessibility Inspector是展示元素的可用性,
Label 对应 accessibilityLabel属性,控件信息,触摸时首先被朗读的
Traits 对应 accessibilityTraits属性,控件类型和特征,比如说 按钮、变灰
Frame 对应 accessibilityFrame属性 ,朗读时在屏幕上显示的聚焦框位置和大小,一般不需改动。
可以通过编写代码
button.accessibilityLabel = @"请点击一下";
button.accessibilityHint = @"可以进入到新页面";
可以得到结果,voiceOver信息就会变成请点击一下 按钮 可以进入到新页面
6.针对几种元素进行VoiceOver开发
(1)标准控件
标准控件默认支持VoiceOver,只需要通过UIAccessibility接口设置对应的属性就可以达到大部分的无障碍支持需求,用的比较多的属性有:
accessibilityLabel:此属性用于描述控件的功能或内容,当用户触摸到控件区域,就会播放相应的描述内容;accessibilityTraits:UIAccessibilityTraits,用于描述控件的特性,是一个组合属性,即可以通过多个UIAccessibilityTraits或操作组合属性。对于标准控件,都有其默认值描述对应控件的特征,而自定义控件的默认值为UIAccessibilityTraitNone,举个例子,UIButton该属性默认值为UIAccessibilityTraitButton,当用户触摸时将会播放accessibilityLabel的描述内容+“按钮”,如果按钮被disable,则应该像如下设置此属性,表示该元素 是 按钮且变灰(点击无效)
stopElement.accessibilityTraits = UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled;
accessibilityHint:用于描述控件激活后的动作,一般是一个动词开头的短语;
accessibilityElementsHidden:是一个BOOL属性,用于隐藏控件,使控件不响应VoiceOver触摸,设置控件的hidden属性只能隐藏控件的可视区域,但是对VoiceOver是无效的,如果要使控件不响应VoiceOver,将此属性设置为YES.
(2)自定义控件(UIView的某些子类)
默认情况下自定义控件是不支持VoiceOver的。可以通过两种方式使其支持VoiceOver:
1)实现isAccessibilityElement协议,在UIView子类中实现此协议返回YES;
2)直接设置isAccessibilityElement属性,将其设置为YES; 自定义其他属性和标准控件一样
tips:
a.父View如果设置isAccessibilityElement为YES,则其子View将都不能相应VoiceOver,如果如果需要两个View都支持VoiceOver,只能改变他们的层次结构,并都设置为isAccessibilityElement.
b.在某些情况下,希望控件在VoiceOver模式下直接处理touch事件,比如,画图功能,画布需要处理触摸事件,而在voiceOver开启的情况下,touch事件会被block,这时就需要设置画布的accessibilityTraits: paintCanvas.accessibilityTraits |= UIAccessibilityTraitAllowsDirectInteraction;
(3)其他情况
在自定义view中有时包含了一些非标准控件也非UIView子类的可触摸UI原素,比如通过draw方法画出来的区域,则以上的两种情况都不能实现无障碍体验,这种情况下,则需要实现UIAccessibilityContainer Protocol来实现.UIAccessibilityContainer Protocol是非正式协议,只需要实现以下接口:
1)定义一个NSMutableArray属性 用于保存所有的accessible Elements. @property(nonatomic, strong) NSMutableArray *accessibleElements;
2)– (NSInteger)accessibilityElementCount方法,返回Element个数;
3)– (id)accessibilityElementAtIndex:(NSInteger)index;返回对应index下的UIAccessibilityElement;
4)实现- (bool)isAccessibilityElement;返回NO,正如之前提到,父View如果为AccessibilityElement,子element将不响应voiceover,所以这里要返回NO; 在生成每个区域的UIAccessibleElement需要定义element关联的frame,,其它的和标准控件一致,举例子(在官网中也有例子说明),比如如下这段:
UIAccessibilityElement *element = [[UIAccessibilityElement alloc]initWithAccessibilityContainer:self];
element.accessibilityFrame = [self convertRect:_nameLabel.frame toView:nil];
element.accessibilityLabel = NSLocalizedString( _nameLabel.text, nil);
element.accessibilityTraits = UIAccessibilityTraitStaticText;
[_accessibilityElements addObject:element];
(4)通知
1)在进入界面是将VoiceOver焦点定位到特定控件。可以使用UIAccessibilityPostNotification发送通知给特定控件,改变voiceOver焦点:
@implementation MyViewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
self.myFirstElement);
}
@end
2)直接播一段语音
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @"something to read aloud");
(5)其他
长按在voiceOver下的操作:选中,轻点两下,再按住;解释见
http://www.applevis.com/forum/ios-ios-app-discussion/how-do-you-perform-long-press-action-using-voice-over
参考资料
http://nshipster.cn/uiaccessibility/
http://useyourloaf.com/blog/voiceover-accessibility.html
http://bupojung.github.io/blog/2014/06/24/wei-mang-ren-dao-hang-voiceoverzong-jie/