W3C

无障碍专题交流

2022年9月7日

题目:基于规则的无障碍适老化开发框架

讲者:许怀鑫(微信 安卓客户端开发工程师) [演示文稿]

现场纪要

许怀鑫:

许怀鑫:大家下午好,我是微信这边负责开发安卓框架的许怀鑫。我把这个框架命名为基于规则的无障碍的框架。

这是接下来的大纲,首先是框架需求及背景。可感知性,可操作性和可理解性。

刚才讲到可感知性、可操作性、可理解性,框架是针对可操作性和可理解性这两个来做的。在去年的上半年之前,我们对无障碍这一块的关注是比较少的,直到工信部发布了无障碍的要求,我们这一块才会重视起来。

去年接到通知说要搞无障碍的技术要求是在五六月份,留给开发的时间非常的少,而且工作量很大。而且对开发的同学而言,对无障碍的接触是比较少的。而且每一个开发要阅读无障碍的开发文本,代价比较大。

而且这种代码的侵入性比较大,有时候适配无障碍的需求,并不是添加一两个无障碍的属性就可以实现的。

所以我们开发这个框架很大目的是为了节省人力,在短短的两三个月内又快又好的做好无障碍这个事,我们需要框架把重复的逻辑给抽离出来,对特定的业务逻辑,需要包装一些简单的接口,去减少其他开发的一些学习成本。

这是我们框架的目前实现的一些功能。

第一个是全局的热区宽高补齐,太小的空间对于用户无论是否是释放用户或者说其他的用户都是不友好的,所以我们需要全局的热区补足机制。

还有平时需要的功能,比如说设置适配的文案,还有冗余焦点的禁用,还有一些拓展的功能。具体的功能就不多介绍了,感兴趣的话可以在群里一起交流。

分享框架之前介绍一下应用安卓系统及读屏软件的配合流程。应用上的每一个页面都有控件组成的控件数,安卓会把这些控件数进行修饰,添加无障碍的属性,设置成虚拟的读屏数,呈现给软件。

后面会很大程度上利用到虚拟节点数这一部分。

事件的分发流程,当用户的事件进入的时候,每一个控件中都有一个虚拟的节点,简单的来说系统会向应用索取每一个独立的节点,将这些虚拟节点拼成一个读屏软件。

通过设置一个大类,在控件提供虚拟节点给系统的时候,中间件有拦截,对这些虚拟节点进行一些特殊的处理,这样的话做到在不改变原有节点的情况下,做一个无障碍的适配。

框架的整体流程就是这样的,我们会在每一个控件创建的时候设置一个节点的拦截,在系统生成节点的时候进行配置,最后在交给读屏软件。现在看这个流程可能会有一点抽象,我们有一个概念就可以了。

第一个核心的功能就是热区补足机制,对于这些点击区域过程中的控件,如果要进行适配的话,可能要具体找到它业务里面点,改动一些布局,这时候需要全区的补足机制。在创建View的统一入口去设置TOUCHDELEGATE代理。

这里有一个很关键的问题就是如何找到一个合适的父亲?这里面的流程还算清晰,首先是需要确定当前的控件是否需要扩大,需要去计算扩大的热区的大小,寻找一个合适的父亲,怎么样算一个合适的父亲呢?

首先第一个这个父亲是足够大的,足够容纳孩子扩大后的热区,这是其中一个合适的条件之一。

这里面在处理的过程中也遇到一些问题,如果存在一个子VIEW是CLICKABLE,这时候尝试做出一个牺牲,当冒号到一个父亲是可点击,我们就不再向上寻找,最终效果是右边的图。

尽管效果并不完美,但是最起码可以做到它是在优化它的区域比原本更大了,针对这样特殊的情况,再进行一些处理。

通过的情况通过阅读可以了解到,在派发的过程中,孩子在处理事件的优先级是高于父亲的,为了防止在拦截掉,我们会把把它设置为父亲的或者。

下面是一些成果的展示,上下对比可以看到区域是明显进行了放大,效果还是OK的。

对于这一套热区补足机制是通用的逻辑,这里主要介绍一下对元素类型的规范,首先我们知道一个按纽的读屏是由读屏软件拼接起来的,描述+类型+行为,比如说按纽读屏,点按纽两次进入。

有部分的控件是没有这个类型组件的,它不会读按纽这两个字,为什么?它只是一个图片,右边是一个文本框,这样的话我们怎么样让,理想的状态应该是读出类型按纽,对用户来说是比较好的。

对于这种微信设置页中,我们希望这样的整个被按纽识别,之前有开源过一版原码,在学习原码的过程中,LALKBACK根据CLASSNAME来判定是否集成BUTTON。

我们解决的方案特别的简单,就是在框架中没有生成虚拟节点之后,手动的将这个节点中的CLASSNAME设置成BUTTON.CLASS,这样的话又简单又容易。

下一个是非通用逻辑的处理,业务中各种各样的特殊逻辑需要自己处理,比如说一些控件的描述,通常会把代码插入,代码非常的分散,尤其是遇到特殊的情况,甚至有一些适配难以实现,在这里可以对控件进行处理。

罗列了几个简单的问题,当我们遇到需求,可点击区域会选读屏软件是否开启变化,右边的按纽会响应,但是开启了读屏的时候,整个没有得到响应,怎么样实现呢?通常情况下会给它加一个点击的事件,加一些碰撞,如果当前软件启动了,我就响应,不启动就不响应吗?这样的话很不优雅。

选中了头像,比如说腾讯行政的头像有两条未读的消息,但是做起来比较难做。有时候会有聚焦修改的适配需求,我们这里要求顺序是ABB或者说ABA,或者说交换出现,都不是一直出现的。这时候要么改里面控件的定义,要么用下面这两个API写一堆前后的描述。

为了帮右侧解决这种难以实现的问题和需求,框架这边就基于这套拦截实现了配置池,由右侧定义自己特殊的规则,在控件页生成节点的时候,应用它特定的规则修改节点的属性,右边是的流程就是这样的,可以看到右侧是直接配置池进去以后,控件在生成节点的时候,框架拦截节点,去配置池里面搜索有没有合适的规则,然后进行数据的更新,再提供给读屏软件。

这样的话系统比较优雅的做法,而且业务也不需要去在它原本的很多代码里面寻找应该添加哪些部分,把无障碍的代码,无障碍相关的适配代码耦合在逻辑之中。

这里面为了防止配置池过大不利于维护的问题,我们将框架设计成不规则配置,这样的也容易维护和拓展,耦合性高。

最后简单的介绍一下在使用框架情况下,怎么样简单的适配刚刚提到的一些需求。

比如说右边是定义两个规则,通过这几行代码就可以实现这样的需求。还有一些聚焦顺序的改变,定义了三个规则,将边框外层的控件读屏文案设定成里面编辑框的文本,并且用内部的编辑框的焦点。第二个规则是进入到页面是聚焦而不是编辑框。第三个规则是定义一个聚焦链路,以一种比较合适的驱动修改它的聚焦顺序,不需要设特殊的其他的属性。

接下来介绍一些工具,上一位朋友提到说,最开始初步的工作是非常多的,页面的元素非常多,而且我们找茬的效率比较低下,所以我们会实现做一个工具,把所有所聚焦的框架都标出来,提升找茬的速度。

原理也比较简单,就是写了一个无障碍的Accessibilityservice,对所有的阶段进行判断。这里有一个关键点,就是怎么样判断?一个节点就是是否被聚焦。赌一下原码,把那一部分拷贝过来,具体怎么样碰撞、聚焦的,这里面时间的关系就不多说了,感兴趣的话可以在群里跟我交流。

微信里面也写过一篇文章,发在一个微信的技术公众号上,里面有详细的介绍它怎么样聚焦一个框架的。我的分享就到这里,希望帮助到其他的客户端开发的同学,以一种低成本的模式做好无障碍适配的模式。谢谢大家!

主持人:谢谢怀鑫,线上有一位用户想了解一下安卓版文本朗读的状况是怎么样的,收到PDF软件的时候,能否打开界面朗读的支持?他自己的体验是打开有显示,但是无法朗读。

许老师:在聊天中点出一个PDF文件中进行读屏吗?

主持人:对。

许老师:我们这边对这种PDF文件浏览处理使用的是范文里面渲染的,不属于原生开发的范畴,这一块框架也只能针对原生开发。因为这一套框架所有的流程都是基于控件能够生成节点,我们可以拦截这个节点的前提下。

但是那边产生的虚拟节点,我们是无法拦截到的,以及还有其他的新的技术,它们的生成节点的规则又不太一样,目前不是用于这套框架。

主持人:这个问题我们刚才也邀请许老师进群了,群里有一些不同软件读屏的开发者,我们可以在群里面沟通。

返回会议总结主页


若您对上述内容有任何疑问或需进一步协助,请联系:讲者冉若曦 <ran@w3.org> 或会议主办方 W3C 北航总部 <team-beihang-events@w3.org>。