关于支持 VoiceOver

本文详细介绍了如何适配iOS的VoiceOver功能,包括UILabel、UIButton的自动支持,自定义View的适配方法,如设置isAccessibilityElement、accessibilityLabel等属性。同时,讲解了Texture的适配技巧,自定义语音播放及Toast内容读取,自动聚焦,自定义事件的实现,以及自定义Alert和ActionSheet的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Voice Over 是苹果出的为方便视力障碍人士使用手机的功能,打开后就可以把屏幕上的内容用语音读出来。通常开发的 app 很少考虑到这个功能,也没有做适配。但是 UILabelUIButton 本身是支持 Voice Over的,不用做适配都可以自动读出来。但是自定义 View 这样的还是需要做一下适配会体验比较好一点。

一、适配

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

@property(nonatomic) BOOL isAccessibilityElement;

@property(nonatomic, copy) NSString *accessibilityLabel;

@property(nonatomic, copy) NSString *accessibilityHint;

@property(nonatomic) UIAccessibilityTraits accessibilityTraits;

@property(nonatomic, copy) NSString *accessibilityValue;

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

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

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

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

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

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

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

2、对于自定义 View,包括 cell,会有很多状态,显示的内容都是根据状态来的,那么这时候重载的话,就可以把这部分代码写在一起,和 正常的代码区分开。

二、Texture 的适配

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

但是有个问题就是 Texture 本身没有处理 控件的 accessibilityElementsHidden 属性。而且也没有判断子控件的状态是显示还是隐藏,只是 遍历了子控件,能读的就给读出来。所以 Texture的适配就是 判断隐藏的子控件,不能用隐藏方法,只能是直接不添加,不调用addSubnode

三、播放自定义语音,自动读出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);
});
复制代码
四、自动聚焦

直接上代码

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, VIEW);
复制代码
五、自定义事件

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

初始化后,可以绑定到控件的

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

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

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

六、提示框 Alert & Actionsheet

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

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

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

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

参考:

blog.csdn.net/heyc861221/…

blog.csdn.net/u010850094/…

blog.csdn.net/heyc861221/…

www.logcg.com/archives/23…

转载于:https://juejin.im/post/5c0dc701f265da61620d390d

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值