Android TV 上的自定义视图无障碍功能支持

虽然许多 Android TV 应用都是使用原生 Android 组件构建的,但也请务必考虑第三方框架或组件的无障碍功能,尤其是在使用自定义视图时。

直接与 OpenGL 或 Canvas 对接的自定义视图组件可能无法很好地与 Talkback 和开关控制等无障碍服务配合使用。

请考虑开启 Talkback 后可能会出现的一些问题:

  • 无障碍功能焦点(绿色矩形)可能会在您的应用中消失。
  • 无障碍功能焦点可能会选择整个屏幕的边界。
  • 无障碍功能焦点可能无法移动。
  • 方向键上的四个方向键可能不起作用,即使您的代码会处理这些按键。

如果您在应用中发现上述任何问题,请检查您的应用是否向无障碍服务公开了其 AccessibilityNodeInfo 树。

本指南的其余部分提供了一些解决这些问题的解决方案和最佳做法。

无障碍服务使用方向键事件

此问题的根本原因是无障碍服务使用了按键事件。

方向键事件消耗 图 1. 此图展示了系统如何在 TalkBack 开启和关闭的情况下运行。

如图 1 所示,当 TalkBack 开启时,方向键事件不会传递到开发者定义的方向键处理程序。相反,无障碍服务会收到按键事件,以便移动无障碍服务焦点。由于自定义 Android 组件默认不会向无障碍服务公开有关其在屏幕上位置的信息,因此无障碍服务无法移动无障碍功能焦点以突出显示它们。

其他无障碍服务也会受到类似影响:使用“开关控制”时,可能还会使用方向键事件。

由于方向键事件会提交到无障碍服务,并且该服务不知道界面组件在自定义视图中的位置,因此您必须为应用实现 AccessibilityNodeInfo 才能正确转发按键事件。

向无障碍服务公开信息

如需向无障碍服务提供有关自定义视图的位置和说明的足够信息,请实现 AccessibilityNodeInfo 以公开每个组件的详细信息。如需定义视图的逻辑关系,以便无障碍服务管理焦点,请实现 ExploreByTouchHelper,并使用 ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat) 对自定义视图进行设置。

在实现 ExploreByTouchHelper 时,请替换其四个抽象方法:

Kotlin

// Return the virtual view ID whose view is covered by the input point (x, y).
protected fun getVirtualViewAt(x: Float, y: Float): Int

// Fill the virtual view ID list into the input parameter virtualViewIds.
protected fun getVisibleVirtualViews(virtualViewIds: List<Int>)

// For the view whose virtualViewId is the input virtualViewId, populate the
// accessibility node information into the AccessibilityNodeInfoCompat parameter.
protected fun onPopulateNodeForVirtualView(virtualViewId: Int, @NonNull node: AccessibilityNodeInfoCompat)

// Set the accessibility handling when perform action.
protected fun onPerformActionForVirtualView(virtualViewId: Int, action: Int, @Nullable arguments: Bundle): Boolean

Java

// Return the virtual view ID whose view is covered by the input point (x, y).
protected int getVirtualViewAt(float x, float y)

// Fill the virtual view ID list into the input parameter virtualViewIds.
protected void getVisibleVirtualViews(List<Integer> virtualViewIds)

// For the view whose virtualViewId is the input virtualViewId, populate the
// accessibility node information into the AccessibilityNodeInfoCompat parameter.
protected void onPopulateNodeForVirtualView(int virtualViewId, @NonNull AccessibilityNodeInfoCompat node)

// Set the accessibility handling when perform action.
protected boolean onPerformActionForVirtualView(int virtualViewId, int action, @Nullable Bundle arguments)

如需了解详情,请观看 2013 年 Google I/O 大会 - 在 Android 上启用盲人和低视力无障碍功能,或详细了解如何填充无障碍事件

最佳实践

试阅内容

请参阅 Android TV 的自定义视图无障碍功能示例,了解为使用自定义视图的应用添加无障碍功能支持的最佳实践。