虽然许多 Android TV 应用都是使用原生 Android 组件构建的, 还要考虑到第三方的可访问性 框架或组件,尤其是在使用自定义视图时。
直接与 OpenGL 或画布对接的自定义视图组件可能无法正常运行 以及 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)
有关详情,请观看 Google I/O 2013 - 辅助盲人和弱视者观看 Android 上的无障碍功能 或详细了解如何填充无障碍事件。
最佳做法
必需:
AccessibilityNodeInfo.getBoundsInScreen()
必须定义组件的位置。必需:
AccessibilityNodeInfo.setVisibleToUser()
必须反映组件的可见性。必需:
AccessibilityNodeInfo.getContentDescription()
必须指定内容说明,以便 Talkback 播报内容。指定
AccessibilityNodeInfo.setClassName()
以便服务区分组件类型实现
performAction()
时, 使用相应的AccessibilityEvent
来反映操作。如需实现更多操作类型(例如
ACTION_CLICK
),请调用AccessibilityNodeInfo.addAction(ACTION_CLICK)
使用performAction()
中的相应逻辑。在适用情况下,反映
setFocusable()
的组件状态,setClickable()
,setScrollable()
, 以及类似的方法。查看有关
AccessibilityNodeInfo
的文档 以便发现无障碍服务可以通过哪些其他方式更好地与 组件。
示例
请参阅适用于 Android TV 的自定义视图无障碍功能示例,了解适用于 为使用自定义视图的应用添加无障碍支持。