目前中國有1700多萬視障人士,他們渴望購物,也希望在任何情況下都能平等的獲取他們想要的信息,手淘作爲全國最大的購物 App,我們也希望通過技術讓視障消費者能更好的享受移動互聯帶來的便利,這既是公益,也是義務。

本文將和大家分享手淘在使用 DinamicX 支持無障礙的技術方案,並給出了相關示例,希望對移動端開發者有所啓發。

什麼是無障礙?

無障礙範圍很廣,一般是指在發展過程中沒有阻礙,活動能夠順利進行。比如給腿腳不便的人在一些公共場合比如火車站、機場、商場等地方設置無障礙電梯,無障礙廁所,或者給聽覺障礙的人提供助聽器等等。

換句話說:爲失能人士提供與非失能人士同等機會。這裏所說的失能根據具體形式和嚴重程度各不相同,但主要可以分爲四種:認知、視覺、聽覺,以及活動能力。

當然失能也分爲兩種永久性失能和情境性失能。

永久性失能:

  • 視覺障礙、聽覺障礙、坐輪椅或者行動不便等肢體障礙

情境性失能:

  • 開車的時候試圖用手機:汽車晃動導致情境性的視覺障礙、肢體障礙、注意力障礙

  • 開會時聊天軟件發來語音:查看消息發出聲音會影響周圍同事(好的聊天軟件提供語音轉文字的功能便是無障礙的一種)

  • 出國旅遊語言不通:情境性的口頭溝通障礙

  • 買東西時拎着大包小包:情境性的肢體障礙

無障礙的新定義:確保每個用戶意圖都被理解

某種程度而言,信息無障礙是智能產品交互設計中針對特殊人羣的一個功能,它可以讓人們更加平等地享用產品在硬件和軟件上的各項功能。

阿里無障礙的歷程

DinamicX對無障礙的支持

▐   目標與定位

通過技術手段,幫助視障人羣更好地感受世界的美好,讓用戶在使用app的時候能夠順暢的獲取信息、利用信息。

▐   DinamicX

DinamicX  SDK  作爲支撐手淘基礎核心鏈路重要的一環,首當其衝肩負起支持無障礙的功能。

手淘基礎核心鏈路?

手淘首頁、詳情、購物車、下單、訂單、訂單列表、我的淘寶都屬於手淘核心鏈路,目前上述頁面UI都是使用DinamicX作爲渲染引擎來繪製。

什麼是DinamicX?

DinamicX的定位是一個提供三端統一能力的客戶端動態化解決方案,爲無線基礎鏈路上的高性能和高可用提供基礎保障。我們希望通過社區化運營不斷豐富DinamicX的能力和內容,提高渲染性能和穩定性,將DinamicX打造成一個集團內的客戶端動態化體系的標準化方案。

動態模板解決方案核心技術: 一個包含模板的下載、加載、解析、渲染的引擎,幫你動態生成View。

講完DinamicX,接下來我們講DinamicX對無障礙的支持。

DinamicX對無障礙的支持主要分爲兩部分:

  • SDK本身對無障礙的跨平臺支持

  • 模板開發平臺進行卡口校驗

作爲一個跨平臺統一的動態化解決方案,勢必要抹平端與端的差異,以及降低業務方(模板開發者)想支持無障礙的認知成本,我們團隊全體成員包括Android、iOS、以及測試同學討論了很久,確保兩端統一的情況下,勾勒出統一無障礙行爲。

▐    技術方案

系統原生的無障礙

✎   iOS 系統原生的無障礙

原生iOS的幾種邏輯

  • View設置了 isAccessibilityElement=YES,無論是否設置了 accesibilityLabel,所有它的子節點,都不可獲得焦點;

  • UILabel的isAccessibilityElement屬性默認是NO,但只要主動地設置過值,就算設置的是NO,也無法在父容器下自動讀出;

  • 如果需要父容器獲得焦點後自動讀取出裏面所有UILabel的文字,需要isAccessibilityElement = NO,並且 accessibilityElementsHidden = NO。Label 的 isAccessibilityElement 必須保持原始默認值,不能設置任何值;

  • 如果父節點嵌套,並且所有父節點的 accessibilityElement 都設置爲 off,會自動將 這個父節點所有的子節點的TextView的 accessibilityLabel 順序讀出,這意味着所有自動閱讀的文字最終都在根節點上被讀出。

系統無障礙API

✎   Android 系統原生的無障礙

Android 的View無障礙狀態總共分爲3種:

  • 沒有無障礙信息 ,如ImageView、View等 默認就是沒有無障礙信息

  • 有無障礙信息 ,如ImageView設置setContentDescription,或者TextView自帶無障礙信息就是它本身的text

  • 有無障礙信息的可交互控件 ,比如ImageView設置setContentDescription的同時,又設置了setOnClickListener, 比如TextView設置了setFocusable(true),或者EditText、CheckBox這種默認就是有無障礙信息的可交互控件

這3種無障礙狀態在它的父layout之中的關係

系統無障礙API

▐   DinamicX SDK定義無障礙屬性

抹平兩端差異,簡化無障礙邏輯,DinamicX提供了兩個無障礙屬性來支持無障礙功能。

xml示例

如下表示該控件在觸摸到的時候,會被選中,且朗讀出“跳往詳情頁”的文案

<ImageView
            width="100"
            height="100"
            accessibility="on"
            accessibilityText="跳往詳情頁"
            onTap="@openUrl{'detail'}"
            imageUrl="https://img.alicdn.com/tfs/TB1FuMQQFXXXXXLXXXXXXXXXXXX-420-420.jpg"
        />

▐    統一兩端無障礙行爲

下圖代表的是兩端目前統一行爲,描述了Layout與子節點在無障礙屬性各種value值碰撞下的情況。

▐    端上的處理

爲達到上圖所展示的兩端一致的行爲,端上各自做了自己的處理。

✎   iOS

下圖表示SDK根據模板屬性到系統 API 的映射

✎   Android

以下圖片表示SDK根據模板屬性到系統API的映射:

Android對Layout和非Layout的View需要區別對待。

Layout節點對無障礙的處理

非Layout節點對無障礙的處理

▐   案例演示

✎   模板示例

<LinearLayout
    backgroundColor="#eeeeee"
    height="match_content"
    width="375"
    orientation="vertical"
    disableFlatten="true"
>
    <LinearLayout
        marginLeft="@triple{@data{cellType},20,50}"
        backgroundColor="#f2f2f2"
        height="match_content"
        width="match_parent"
        orientation="vertical"
        disableFlatten="true"
        accessibility="auto"
    >
        <!--auto代表點擊的時候,該layout下面的text信息都可以讀出來-->
        <TextView
            width="match_content"
            height="match_content"
            textColor="#ff051b28"
            textSize="12"
            marginTop="20"
            marginBottom="20"
            text="這是一個textView"
        />
 
        <TextView
            width="match_content"
            height="match_content"
            textColor="#ff051b28"
            textSize="12"
            marginTop="20"
            marginBottom="20"
            text="這是一個有焦點的textView"
            accessibility="on"
            onTap="@rTap{}"
            accessibilityText="這是一個有焦點的textView"
        />
 
        <FastTextView
            width="match_content"
            height="match_content"
            textColor="#ff051b28"
            textSize="12"
            marginTop="20"
            marginBottom="20"
            text="這是一個FastTextView"
        />
 
        <TextView
            width="match_content"
            height="match_content"
            textColor="#ff051b28"
            textSize="12"
            marginTop="20"
            marginBottom="20"
            accessibility="off"
            text="這是一個不需要被朗讀的textView"
        />
 
        <ImageView
            width="100"
            height="100"
            marginLeft="20"
            marginTop="12"
            borderWidth="3ap"
            borderColor="#FF0000"
            accessibility="on"
            accessibilityText="這是一個ImageView點擊"
            onTap="@rTap{'測試'}"
            imageUrl="https://img.alicdn.com/tfs/TB1FuMQQFXXXXXLXXXXXXXXXXXX-420-420.jpg"
        />
    </LinearLayout>
</LinearLayout>

✎   模板示例手機演示

看如下視頻,由於Layout accessibility設置了auto屬性,因此該Layout會被選中,並朗讀內部含有無障礙信息的Text,但是第二個和第四個TextView是不會朗讀的,第二個配置了onTap&accessibility="on",因此此時它屬於一個可交互的控件,是需要單獨被選中的,第四個accessibility="off",因此此時它是關閉無障礙這個功能的,因此也沒法選中朗讀,且不會被Layout選中朗讀。

▐   無障礙校驗卡口

支持是一方面,引導開發同學去寫是另一方面。

事實上現在好多動態化的方案,包括native本身都會支持無障礙功能,但是這種支持是單向的,如果你只是支持,但是開發者不去支持,那最終這個產品無障礙功能依舊是缺失。

開發者爲什麼不去支持呢?

  • 第一 無障礙的公益宣導不夠,優先級不高,開發本身沒有這個意識,無障礙測試用例缺失

  • 第二 無障礙功能的支持有一定的成本,且沒有一套標準和規範告知什麼情況下需要無障礙,且如何支持

  • 第三 流程上沒有監督和管控,開發有可能會忘記

爲了更好的支持幫助視障用戶使用手機淘寶,同時幫助業務方定位發現無障礙的錯誤,減少無障礙的測試 迴歸 工作量, 我們發起了無障礙校驗卡口 ,智能檢測無障礙問題,通過調用無障礙服務來判斷模板是否合格,以此確保每一個模板的發佈都是支持無障礙的。

添加無障礙校驗卡口 這纔是無障礙工作最關鍵的一環,目前由於手淘的核心鏈路都使用的DinamicX,且DinamicX模板都在組件平臺開發,因此只要我們加上這卡口,你想不支持無障礙都不行,否則你的動態模板發佈不了。

擁有無障礙校驗卡口功能的DinamicX開發模式流程圖:

目前無障礙卡口校驗的相關規則(有些校驗規則也是爲了抹平兩端差異而加的):

  • 非交互性控件,如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屬性不能設置動態表達式

如下視頻,假設Layout節點上面設置onTap點擊事件,那麼校驗卡口會提醒你該節點需要設置無障礙信息:

現階段整個手淘首頁、詳情、購物車、我的淘寶、訂單詳情、訂單列表等核心頁面所開發的模板都會經過該卡口的校驗。

願景

也許我們做的不一定是最好的,但是我們會一直努力去做,不爲別的,只是爲了讓手淘在大衆心中特別是盲人的心中除了是一個購物app之外,更是一個溫暖的產品,一個讓盲人感動的產品。

希望有一天我們的開發同學開發模板的時候,再也不需要彈起那個卡口的校驗,而是寫模板的那一刻,已經想起了那些拿着手機耳邊聽的人羣。

希望有一天手淘是盲人心目中最喜歡的購物產品。

希望有一天看到這篇文章的同學們能夠在心裏有那麼一絲觸動,不是道德綁架,而是在未來某一天盲人談起手淘那種由衷的感謝可以帶給自己心靈的那種慰藉。

希望有一天看到這篇文章的同學能夠感受到:無障礙是一件公益,做完心裏暖暖的,技術除了有價值以外,還可以有溫度的。

重視無障礙 重視公益 從我們做起!

藉助手機旁白功能,視障者用耳朵購物

淘寶無障礙實驗室工程師閉着眼睛做無障礙測試

手淘客戶端跨平臺技術部

歡迎大家加入 手淘客戶端跨平臺技術部 !是支撐DinamicX、小程序、小遊戲、Flutter 等跨平臺技術的核心團隊,有技術廣度和也有技術深度,我們需要 iOS、Android、C++、Flutter、Canvas、WebGL、WebAssembly 等各方面的人才。如果你善於學習,這是一個很好的接觸跨領域知識的機會!

郵箱:postbox:: [email protected]

手淘客戶端中間 件技術架構

歡迎大家加入 手淘客戶端中間件技術架構 !團隊主要負責手淘移動端的基礎PaaS及架構。負責包括移動網關、網絡加速、長連通道、圖片體驗等網絡優化;負責包括海量消息推送、站內業務浮層等流量技術;並對移動端系統進行前沿探索,打造了全站IPv6、iOS用戶態網絡棧、Android最小核、自適應線程調度等高性能技術和架構。

我們期待有技術、有理想的你加入,與我們共享積極、透明、開放的團隊氛圍,伴隨着各種乾貨滿滿的分享培訓以及業務和技術挑戰,我們將一同在技術領域不斷攻堅、推陳出新,共同駛向屬於我們的星辰大海。

職位: iOS 開發、Android 開發、C++開發、Java 服務端開發、前端開發、數據工程師、算法工程師

郵箱:postbox:: [email protected]

✿  拓展閱讀

作者| 大飽

編輯| 橙子君

出品| 阿里巴巴新零售淘系技術部

相關文章