语义可见性

背景

当用户与屏幕的某个部分进行互动时,系统会执行点击测试,以确定该互动要发送到哪个视图。目前,有两种类型的 hit regions:语义上可见的和语义上不可见的。

HitTestInteraction 枚举会指定语义(无障碍功能)命中测试是否应与之交互。

语义可见的命中区域与常规命中测试和 accessibility hit testing 交互,而语义上不可见的命中区域仅与常规命中测试(例如来自鼠标或触摸事件)交互。

智能型展示广告系列案例研究

为了更好地了解为什么我们需要语义可见性作为属性,不妨查看一下激励性示例。以智能显示屏产品为例,它本质上是一个 Flutter 应用,有时可以启动子应用,如 WebView。

父 Flutter 应用可以启动一个包含 YouTube 播放器的子网页视图。出现这样的情况:一些命中应转到 YouTube(例如播放或暂停视频),而另一些命中应由父级进程处理,例如一个完全关闭播放器的手势。由于两个视图都是全屏视图,因此就没有那么简单了。

一种解决方案是让 Flutter 父级进程将一个全屏、透明且语义隐形的点击区域作为最顶层的视图区域。我们将此视图称为“输入护罩”。借助输入屏蔽,Flutter 可以拦截所有输入,包括那些用于 YouTube 播放器的输入,然后根据需要使用或重定向输入。

为了更好地理解此输入护罩在语义上不可见的原因,我们来看一下无障碍功能的探索模式,来考虑如果不这样做会发生什么。当用户在屏幕上拖动手指时,此模式即为 a11y 管理器读出用户手指触摸的所有内容。这些无障碍功能点击测试想要忽略输入护罩,而是读出其下的“真实”内容。

通过将输入护罩在语义上设为不可见,这正是目的。无障碍命中仅与语义上可见的命中区域(在本例中为 YouTube 播放器)交互。

示例

简单案例

语义上不可见的绿色视图叠加在语义可见的蓝色视图之上。语义命中测试不会看到语义上不可见的绿色视图,因此会转到蓝色视图。

简单示意图

图片说明:语义上不可见的视图叠加在语义可见的视图之上。因此,与所有视图交互的常规点击测试会触及语义上不可见的顶部视图。语义命中测试会忽略它,因此会命中底部,从语义上看是可见的。

智能型展示柜

从上到下依次为透明视图、红色视图和蓝色视图。透明视图在语义上不可见,并且是全屏视图,而红色和蓝色视图表示用户可能想要与之互动的不同内容,例如 Flutter 运行的网页或应用。 Flutter 内容不会直接接收常规命中(因为这些将由顶级视图处理),但 Flutter 内容将接收语义命中(例如无障碍服务执行的命中),因为语义命中会忽略语义上不可见(且视觉不可见)的顶级视图。

智能显示屏示意图

图片说明:共有三种视图,按照从上到下的顺序,它们分别代表不可见的语义护盾、YouTube 播放器和 Flutter 视图。无论语义可见性如何,常规点击测试都会转到最顶层的视图,因此透明的“输入盾”会接收这些测试。语义点击测试会忽略最顶层的输入盾牌,因此转到最高 Z 级、语义可见的视图:YouTube 播放器。