【问题标题】:Android accessibility: Talkback traverses elements in wrong orderAndroid 可访问性:Talkback 以错误的顺序遍历元素
【发布时间】:2018-01-07 00:10:34
【问题描述】:

我有一个带有工具栏的布局和一个包含其他控件的视图:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ViewStub
        android:id="@+id/root_view_stub"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

使用 FrameLayout 以便具有正“高度”的工具栏可以是半透明的,并且视图可以延伸到工具栏下方。工具栏和视图的顶部位置相同,但高度不同。当 Talkback 构建视图层次结构时,它会将工具栏放在底部,即使它是首先定义的。 “accessibilityTraversalBefore”和“accessibilityTraversalAfter”对视图没有影响。到目前为止,我发现的唯一解决方案是向 ViewStub 添加 1px 或 0.1px 的上边距。这可能与这里的代码有关:

https://github.com/google/talkback/blob/master/src/main/java/com/android/utils/traversal/ReorderedChildrenIterator.java

代码尝试根据节点的屏幕位置重新排序节点。添加上边距有点笨拙,可能有一天会中断。有没有更好的解决方案?

【问题讨论】:

    标签: android accessibility talkback


    【解决方案1】:

    在调试了我的应用和 TalkBack 应用后,我弄清楚了发生了什么。可访问性遍历顺序不受布局中定义的顺序视图的控制。在activity_react_native.xml 中的工具栏或ViewStub 中添加accessibilityTraversalBefore 或accessibilityTraversalAfter 无效。我找不到任何关于遍历顺序的文档,所以我检查了代码。以下是 TalkBack 的工作原理:

    启用 TalkBack 后,所有单指手势都会发送到 TalkBack 而不是应用。这些手势可以在 TalkBack 设置中重新定义。在向上和向下滑动手势之后,TalkBack 首先枚举当前可见页面上的所有可聚焦视图。这是通过向应用程序发送消息来完成的。 在应用程序进程中,可访问性视图层次结构是通过递归遍历所有子视图来构建的。它在 ViewGroup 代码中完成:https://github.com/aosp-mirror/platform_frameworks_base/blob/d18ed49f9dba09b85782c83999a9103dec015bf2/core/java/android/view/ViewGroup.java#L2314。此调用的最后一个参数是硬编码的 true,它根据子视图在屏幕上的位置对子视图进行排序。比较逻辑在这里:https://github.com/aosp-mirror/platform_frameworks_base/blob/d18ed49f9dba09b85782c83999a9103dec015bf2/core/java/android/view/ViewGroup.java#L8397。当两个视图具有相同的顶部、左侧和宽度时,高度较大的视图会排在高度或面积较小的视图之前,这在大多数情况下似乎是一个糟糕的选择。 构建树后,它会被发送回 TalkBack,然后它会根据 traversalBefore 或 traversalAfter 属性对元素进行重新排序。由于 Toolbar 和 ViewStub 不是可聚焦元素,它们不会出现在此树中,这就是这两个属性不起作用的原因。

    修复方法是将 android:importantForAccessibility 添加到工具栏和 ViewStub。这会将它们从 ViewGroup 添加到辅助功能树中,以便 TalkBack 可以对辅助功能遍历之前/之后属性进行操作。

    还有一种解决方法,将工具栏向上移动 1px,然后在内部添加 1px 填充。额外的 1px 应该被 FrameLayout 剪掉,所以没有视觉上的变化:

    android:layout_marginTop="-1px"
    android:paddingTop="1px"
    

    【讨论】:

    • 更新:使用 android:importantForAccessibility 找到了更好的修复方法。更新了我的答案。
    • 非常好的研究!
    猜你喜欢
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2015-10-19
    • 2011-09-29
    • 2013-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多