DinamicX 詳解:如何讓盲人也能在線購物?
目前中國有 1700 多萬視障人士,在互聯(lián)網(wǎng)發(fā)達的今天,他們無法像大部分人一樣享受到互聯(lián)網(wǎng)帶來的便利,比如用手機網(wǎng)購。不過我們可以通過技術來改善這一現(xiàn)狀,最大程度地讓他們的生活更加便捷。本文分享手淘在使用 DinamicX 支持無障礙上的技術方案,并給出了相關示例,希望對移動端開發(fā)者有所啟發(fā)。
什么是無障礙?
無障礙范圍很廣,一般是指在發(fā)展過程中沒有阻礙,活動能夠順利進行。比如給腿腳不便的人在一些公共場合比如火車站、機場、商場等地方設置無障礙電梯,無障礙廁所,或者給聽覺障礙的人提供助聽器等等。
換句話說:為失能人士提供與非失能人士同等機會。這里所說的失能根據(jù)具體形式和嚴重程度各不相同,但主要可以分為四種:認知、視覺、聽覺,以及活動能力。
當然失能也分為兩種永久性失能和情境性失能。
永久性失能
視覺障礙、聽覺障礙、坐輪椅或者行動不便等肢體障礙。
情境性失能
- 開車的時候試圖用手機:汽車晃動導致情境性的視覺障礙、肢體障礙、注意力障礙。
 - 開會時聊天軟件發(fā)來語音:查看消息發(fā)出聲音會影響周圍同事(聊天軟件提供語音轉文字的功能便是無障礙的一種)。
 - 出國旅游語言不通:情境性的口頭溝通障礙。
 - 買東西時拎著大包小包:情境性的肢體障礙。
 
無障礙的新定義:確保每個用戶意圖都被理解。
某種程度而言,信息無障礙是智能產(chǎn)品交互設計中針對特殊人群的一個功能,它可以讓人們更加平等地享用產(chǎn)品在硬件和軟件上的各項功能。
DinamiX 對無障礙的支持
本文接下去講的 DinamicX 對無障礙的支持主要是信息無障礙,一般是針對視覺障礙的人群。通過技術手段,幫助視障人群更好地感受世界的美好,讓用戶在使用 app 的時候能夠順暢的獲取信息、利用信息。
手淘基礎核心鏈路
手淘首頁、詳情、購物車、下單、訂單、訂單列表、我的淘寶都屬于手淘核心鏈路,目前上述頁面 UI 都是使用 DinamicX 作為渲染引擎來繪制。
DinamicX SDK 作為支撐手淘基礎核心鏈路重要的一環(huán),對無障礙的支持責無旁貸。
關于 DinamicX
DinamicX 的定位是一個提供三端統(tǒng)一能力的客戶端動態(tài)化解決方案,為無線基礎鏈路上的高性能和高可用提供基礎保障。我們希望通過社區(qū)化運營不斷豐富 DinamicX 的能力和內(nèi)容,提高渲染性能和穩(wěn)定性,將 DinamicX 打造成一個集團內(nèi)的客戶端動態(tài)化體系的標準化方案。
動態(tài)模板解決方案核心技術:一個包含模板的下載、加載、解析、渲染的引擎,幫你動態(tài)生成 View。
DinamicX 對無障礙的支持主要分為兩部分:
- SDK 本身對無障礙的跨平臺支持
 - 模板開發(fā)平臺進行卡口校驗
 
作為一個跨平臺統(tǒng)一的動態(tài)化解決方案,勢必要抹平端與端的差異,以及降低業(yè)務方(模板開發(fā)者)想支持無障礙的認知成本,我們團隊全體成員包括 Android 開發(fā)、iOS 開發(fā)以及測試同學討論了很久,確保兩端統(tǒng)一的情況下,勾勒出統(tǒng)一無障礙行為。
技術方案
系統(tǒng)原生的無障礙
iOS 系統(tǒng)原生的無障礙
原生 iOS 的幾種邏輯:
- View 設置了 isAccessibilityElement=YES,無論是否設置了 accesibilityLabel,所有它的子節(jié)點,都不可獲得焦點。
 - UILabel 的 isAccessibilityElement 屬性默認是 NO,但只要主動地設置過值,就算設置的是 NO,也無法在父容器下自動讀出。
 - 如果需要父容器獲得焦點后自動讀取出里面所有 UILabel 的文字,需要isAccessibilityElement = NO,并且 accessibilityElementsHidden = NO。Label 的 isAccessibilityElement 必須保持原始默認值,不能設置任何值。
 - 如果父節(jié)點嵌套,并且所有父節(jié)點的 accessibilityElement 都設置為 off,會自動將這個父節(jié)點所有的子節(jié)點的 TextView 的 accessibilityLabel 順序讀出,這意味著所有自動閱讀的文字最終都在根節(jié)點上被讀出。
 
系統(tǒng)無障礙 API:
?? 
Android 系統(tǒng)原生的無障礙
Android 的 View 無障礙狀態(tài)總共分為 3 種:
- 沒有無障礙信息,如 ImageView、View 等默認就是沒有無障礙信息。
 - 有無障礙信息,如 ImageView 設置 setContentDescription,或者 TextView 自帶無障礙信息就是它本身的 text。
 - 有無障礙信息的可交互控件,比如 ImageView 設置 setContentDescription 的同時,又設置了 setOnClickListener, 比如 TextView 設置了setFocusable(true),或者 EditText、CheckBox 這種默認就是有無障礙信息的可交互控件。
 
這 3 種無障礙狀態(tài)在它的父 layout 之中的關系:
?? 
系統(tǒng)無障礙 API:
?? 
DinamicX SDK 定義無障礙屬性
抹平兩端差異,簡化無障礙邏輯,DinamicX 提供了兩個無障礙屬性來支持無障礙功能。
xml 示例
如下表示該控件在觸摸到的時候,會被選中,且朗讀出“跳往詳情頁”的文案:
統(tǒng)一兩端無障礙行為
下圖代表的是兩端目前統(tǒng)一行為,描述了 Layout 與子節(jié)點在無障礙屬性各種 value 值碰撞下的情況。
?? 
端上的處理
為達到上圖所展示的兩端一致的行為,端上各自做了自己的處理。
iOS
下圖表示 SDK 根據(jù)模板屬性到系統(tǒng) API 的映射:
?? 
Android
下圖表示 SDK 根據(jù)模板屬性到系統(tǒng) API 的映射,Android 對 Layout 和非 Layout 的 View 需要區(qū)別對待。
Layout 節(jié)點對無障礙的處理:
?? 
非 Layout 節(jié)點對無障礙的處理:
?? 
案例演示
模板示例
模板示例手機演示
由于 Layout accessibility 設置了 auto 屬性,因此該 Layout 會被選中,并朗讀內(nèi)部含有無障礙信息的 Text,但是第二個和第四個 TextView 是不會朗讀的,第二個配置了onTap&accessibility=on,因此此時它屬于一個可交互的控件,是需要單獨被選中的,第四個accessibility=off,因此此時它是關閉無障礙這個功能的,因此也沒法選中朗讀,且不會被 Layout 選中朗讀。
無障礙校驗卡口
支持是一方面,引導開發(fā)同學去寫是另一方面。
事實上現(xiàn)在好多動態(tài)化的方案,包括 native 本身都會支持無障礙功能,但是這種支持是單向的,如果你只是支持,但是開發(fā)者不去支持,那最終這個產(chǎn)品無障礙功能依舊是缺失。
開發(fā)者為什么不去支持呢?
- 第一,無障礙的公益宣導不夠,優(yōu)先級不高,開發(fā)本身沒有這個意識,無障礙測試用例缺失。
 - 第二,無障礙功能的支持有一定的成本,且沒有一套標準和規(guī)范告知什么情況下需要無障礙,且如何支持。
 - 第三,流程上沒有監(jiān)督和管控,開發(fā)有可能會忘記。
 
為了更好的支持幫助視障用戶使用手機淘寶,同時幫助業(yè)務方定位發(fā)現(xiàn)無障礙的錯誤,減少無障礙的測試回歸工作量,我們發(fā)起了無障礙校驗卡口,智能檢測無障礙問題,通過調(diào)用無障礙服務來判斷模板是否合格,以此確保每一個模板的發(fā)布都是支持無障礙的。
添加無障礙校驗卡口這才是無障礙工作最關鍵的一環(huán),目前由于手淘的核心鏈路都使用的 DinamicX,且 DinamicX 模板都在組件平臺開發(fā),因此只要我們加上這卡口,你想不支持無障礙都不行,否則你的動態(tài)模板發(fā)布不了。
擁有無障礙校驗卡口功能的 DinamicX 開發(fā)模式流程圖:
?? 
目前無障礙卡口校驗的相關規(guī)則(有些校驗規(guī)則也是為了抹平兩端差異而加的):
- 非交互性控件,如 ImageView、FrameLayout、LinearLayout 等,若有設置 onTap 屬性,則會檢查是否含有無障礙屬性,若沒有則校驗不通過,并給出建議:需要設置accessibility=on, 開啟無障礙焦點,同時設置 accessibilityText= xx 屬性。
 - 非交互性控件,如 ImageView、FrameLayout、LinearLayout 等,若有設置accessibility=on 的時候,必須同時設置 accessibilityText=xx。
 - 子 View 設置 onTap 屬性的時候,必須保證它的父 Layout 沒有設置 accessibility=on,否則該子 View 是不能獲取焦點的。
 - 如果 Layout 設置了 auto 屬性,TextView 不能只設置 onTap,還要設置 accessibility=on,否則獲取不到焦點。
 - accessibility 屬性不能設置動態(tài)表達式。
 
假設 Layout 節(jié)點上面設置 onTap 點擊事件,那么校驗卡口會提醒你該節(jié)點需要設置無障礙信息:
現(xiàn)階段整個手淘首頁、詳情、購物車、我的淘寶、訂單詳情、訂單列表等核心頁面所開發(fā)的模板都會經(jīng)過該卡口的校驗。
愿景
也許我們做的不一定是最好的,但是我們會一直努力去做,不為別的,只是為了讓手淘在大眾心中特別是盲人的心中除了是一個購物 app 之外,更是一個有溫暖的產(chǎn)品,一個讓盲人感動的產(chǎn)品。
希望有一天我們的開發(fā)同學開發(fā)模板的時候,再也不需要彈起那個卡口的校驗,而是寫模板的那一刻,已經(jīng)想起了那些拿著手機耳邊聽的人群。
希望有一天手淘是盲人心目中最喜歡的購物產(chǎn)品。
希望有一天看到這篇文章的同學們能夠在心里有那么一絲觸動,不是道德綁架,而是在未來某一天盲人談起手淘那種由衷的感謝可以帶給自己心靈的那種慰藉。
希望有一天看到這篇文章的同學能夠感受到:無障礙是一件公益,做完心里暖暖的,技術除了有價值以外,還可以有溫度。
重視無障礙,重視公益,從我們做起!















 
 
 




 
 
 
 