移动端信息无障碍技术方案全解:以手淘为例

简介: 目前中国有1700多万视障人士,他们渴望购物,也希望在任何情况下都能平等的获取他们想要的信息,手淘作为全国最大的购物 App,我们也希望通过技术让视障消费者能更好的享受移动互联带来的便利,这既是公益,也是义务。本文将和大家分享手淘在使用 DinamicX 支持无障碍的技术方案,并给出了相关示例,希望对移动端开发者有所启发。

image.png


什么是无障碍?

无障碍范围很广,一般是指在发展过程中没有阻碍,活动能够顺利进行。比如给腿脚不便的人在一些公共场合比如火车站、机场、商场等地方设置无障碍电梯,无障碍厕所,或者给听觉障碍的人提供助听器等等。

换句话说:为失能人士提供与非失能人士同等机会。这里所说的失能根据具体形式和严重程度各不相同,但主要可以分为四种:认知、视觉、听觉,以及活动能力。

当然失能也分为两种永久性失能和情境性失能。

永久性失能:

  • 视觉障碍、听觉障碍、坐轮椅或者行动不便等肢体障碍

情境性失能:

  • 开车的时候试图用手机:汽车晃动导致情境性的视觉障碍、肢体障碍、注意力障碍
  • 开会时聊天软件发来语音:查看消息发出声音会影响周围同事(好的聊天软件提供语音转文字的功能便是无障碍的一种)
  • 出国旅游语言不通:情境性的口头沟通障碍
  • 买东西时拎着大包小包:情境性的肢体障碍

无障碍的新定义:确保每个用户意图都被理解

某种程度而言,信息无障碍是智能产品交互设计中针对特殊人群的一个功能,它可以让人们更加平等地享用产品在硬件和软件上的各项功能。


阿里无障碍的历程

v2-da1dd539eeceaf3b44979eea8d882489_720w的副本.jpg


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

image.png

✎  Android 系统原生的无障碍

Android 的View无障碍状态总共分为3种:

  • 没有无障碍信息,如ImageView、View等 默认就是没有无障碍信息
  • 有无障碍信息,如ImageView设置setContentDescription,或者TextView自带无障碍信息就是它本身的text
  • 有无障碍信息的可交互控件,比如ImageView设置setContentDescription的同时,又设置了setOnClickListener, 比如TextView设置了setFocusable(true),或者EditText、CheckBox这种默认就是有无障碍信息的可交互控件

这3种无障碍状态在它的父layout之中的关系

image.png

系统无障碍API

image.png

▐ DinamicX SDK定义无障碍属性

抹平两端差异,简化无障碍逻辑,DinamicX提供了两个无障碍属性来支持无障碍功能。

image.png


xml示例

如下表示该控件在触摸到的时候,会被选中,且朗读出“跳往详情页”的文案

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

统一两端无障碍行为

下图代表的是两端目前统一行为,描述了Layout与子节点在无障碍属性各种value值碰撞下的情况。

image.png


▐ 端上的处理

为达到上图所展示的两端一致的行为,端上各自做了自己的处理。

✎  iOS

下图表示SDK根据模板属性到系统API的映射

image.png

✎  Android

以下图片表示SDK根据模板属性到系统API的映射:

Android对Layout和非Layout的View需要区别对待。


Layout节点对无障碍的处理

image.png

非Layout节点对无障碍的处理

image.png

▐ 案例演示

✎  模板示例 

<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选中朗读。

image.png


无障碍校验卡口

支持是一方面,引导开发同学去写是另一方面。

事实上现在好多动态化的方案,包括native本身都会支持无障碍功能,但是这种支持是单向的,如果你只是支持,但是开发者不去支持,那最终这个产品无障碍功能依旧是缺失。

开发者为什么不去支持呢?

  • 第一 无障碍的公益宣导不够,优先级不高,开发本身没有这个意识,无障碍测试用例缺失
  • 第二 无障碍功能的支持有一定的成本,且没有一套标准和规范告知什么情况下需要无障碍,且如何支持
  • 第三 流程上没有监督和管控,开发有可能会忘记

为了更好的支持帮助视障用户使用手机淘宝,同时帮助业务方定位发现无障碍的错误,减少无障碍的测试回归工作量,我们发起了无障碍校验卡口,智能检测无障碍问题,通过调用无障碍服务来判断模板是否合格,以此确保每一个模板的发布都是支持无障碍的。

添加无障碍校验卡口这才是无障碍工作最关键的一环,目前由于手淘的核心链路都使用的DinamicX,且DinamicX模板都在组件平台开发,因此只要我们加上这卡口,你想不支持无障碍都不行,否则你的动态模板发布不了。

拥有无障碍校验卡口功能的DinamicX开发模式流程图:

image.png

目前无障碍卡口校验的相关规则(有些校验规则也是为了抹平两端差异而加的):

  • 非交互性控件,如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点击事件,那么校验卡口会提醒你该节点需要设置无障碍信息:

image.png

现阶段整个手淘首页、详情、购物车、我的淘宝、订单详情、订单列表等核心页面所开发的模板都会经过该卡口的校验。


愿景

也许我们做的不一定是最好的,但是我们会一直努力去做,不为别的,只是为了让手淘在大众心中特别是盲人的心中除了是一个购物app之外,更是一个温暖的产品,一个让盲人感动的产品。

希望有一天我们的开发同学开发模板的时候,再也不需要弹起那个卡口的校验,而是写模板的那一刻,已经想起了那些拿着手机耳边听的人群。

希望有一天手淘是盲人心目中最喜欢的购物产品。

希望有一天看到这篇文章的同学们能够在心里有那么一丝触动,不是道德绑架,而是在未来某一天盲人谈起手淘那种由衷的感谢可以带给自己心灵的那种慰藉。

希望有一天看到这篇文章的同学能够感受到:无障碍是一件公益,做完心里暖暖的,技术除了有价值以外,还可以有温度的。

重视无障碍 重视公益 从我们做起!

image.png

借助手机旁白功能,视障者用耳朵购物

image.png

淘宝无障碍实验室工程师闭着眼睛做无障碍测试



本篇内容来自阿里巴巴淘系技术部大饱。

点击查看原文

相关文章
|
7月前
|
小程序 前端开发 JavaScript
【经验分享】如何实现在支付宝小程序中开发营销组件
【经验分享】如何实现在支付宝小程序中开发营销组件
81 0
|
7月前
|
Web App开发 前端开发 UED
谈谈你是如何做移动端适配的?
对于移动端适配,一种常用的方法是响应式布局(Responsive Layout)和媒体查询(Media Queries)。以下是一些常见的移动端适配策略:
46 0
|
7月前
|
Web App开发 编解码 前端开发
如何做移动端适配?
如何做移动端适配?
65 0
|
存储 网络协议 调度
淘宝移动端统一网络库的架构演进和弱网优化技术实践
本文将介绍淘宝 APP 统一网络库演进的过程,讲述如何围绕体验持续构建南北向从监测到加速一体化的终端网络架构,通过构建 NPM 弱网诊断感知能力,落地原生多通道技术/多协议择优调度手段,贴合厂商附能网络请求加速,实现去 SPDY 及规模化 IPv6/H3 协议簇的平滑过渡,为用户提供弱网更好、好网更优的 APP 加载浏览体验,支撑业务创造更多的可能性。
374 0
|
开发框架 开发者 前端开发
重磅首发 | 承载亿级流量的开发框架,闲鱼Flutter技术解析与实战大公开
去年闲鱼发布的《Flutter in action》为开发者带去一手的实践经验总结,现在《Flutter in action》全新升级啦!这本书并非基础知识的简单罗列,而是从一线问题出发,循序渐进,娓娓道来。不仅把Flutter的重要理念讲得极为清晰, 而且给开发者提供了应对眼前各种问题的实用方法。同时,书中还给出了详尽的可以融会贯通、举一反三的思路,理论陈述和问题分析面面俱到,力求让读者可以获得全面系统的技术知识。
67638 0
重磅首发 | 承载亿级流量的开发框架,闲鱼Flutter技术解析与实战大公开
|
存储 机器学习/深度学习 算法
优酷移动端组件智能测试方案
随着优酷APP上内容运营方案和玩法的丰富,针对分发和消费业务场景,内容配置平台上的运营组件数量也在增多,移动端的回归测试工作量激增。如何跟随业务发展的脚步,又保证组件测试质量的高效率?本文将分享优酷在该方面的思考和探索
346 0
优酷移动端组件智能测试方案
|
存储 缓存 监控
闲鱼玩法平台系列文章——双11实操篇
你的就是我的,我的还是我的~
2349 0
闲鱼玩法平台系列文章——双11实操篇
|
移动开发 中间件 weex
|
移动开发 小程序 算法
|
数据采集 算法 测试技术