關於支持 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…

相關文章
相關標籤/搜索