实现Fire OS无障碍功能
本页讨论与实现Fire OS无障碍功能相关的概念和术语。
Fire OS无障碍功能对象和事件概述
本节介绍了在应用中实现无障碍功能时将会用到的对象和事件的术语及其定义。
AccessibilityEvent
AccessibilityEvent
是应用向辅助技术发送的消息,指示UI中出现某些问题。可触发无障碍功能事件的UI更改示例包括焦点更改、窗口出现或消失,或者屏幕上的对象更改位置。
请参阅介绍AccessibilityEvents
的Android文档。
AccessibilityNodeInfo
AccessibilityNodeInfo
是屏幕上组件相关无障碍功能信息的快照,主要提供应用和辅助技术之间的单向通信。通过无障碍功能操作,辅助技术也可与应用进行非常有限的通信。
应用创建并返回AccessibilityNodeInfo
后,辅助技术和无障碍功能框架将不会看到对该节点的任何后续更改,因此您此时可以放弃该节点。如果节点表示的基础对象发生更改,则发送一个相应的无障碍功能事件来指示该更改,从而反映在下次调用createAccessibilityNodeInfo
或onInitializeAccessibilityNodeInfo
时所返回节点中对象的更新特征。
在应用中的服务器端,引用节点的方式是使用Android视图和虚拟后代编号的组合。如果节点表示视图本身,则虚拟后代编号为-1 (AccessibilityNodeProvider.HOST_VIEW_ID)
。
应用可以在AccessibilityNodeInfo
对象的getExtras
捆绑包中添加有关该对象的描述性信息,VoiceView可以通过调用AccessibilityNodeInfo.getExtras()来读取该信息。
请参阅介绍AccessibilityNodeInfo
的Android文档。
AccessibilityNodeProvider
AccessibilityNodeProvider
是一个接口,用于为视图或视图实际可访问的后代创建AccessibilityNodeInfo
。
请参阅介绍AccessibilityNodeProvider
的Android文档。
AccessibilityDelegate
AccessibilityDelegate
是一个可以初始化无障碍功能事件、视图节点或实际可访问后代的接口。使用AccessibilityDelegates
,一个视图中的无障碍功能信息可根据另一个视图中的信息进行代表或扩充。例如,父列表可以为某个列表项提供无障碍功能信息。
请参阅介绍AccessibilityDelegate
的Android文档。
无障碍功能事件的路径
本节讨论标准视图和自定义视图的无障碍功能事件路径。
标准视图
构成Fire OS应用用户界面的可视元素称为“视图”。例如,考虑一个具有单个文本元素的简单应用,即一个包含文本“hello world”的TextView
。在此示例中,TextView
是RelativeLayout
的子级。RelativeLayout
是ViewRootImpl
的子级,ViewRootImpl类始终是应用的视图层次结构的根目录。由于TextView
是一个标准的Android视图,因此TextView
的默认行为是在VoiceView运行时发送适当的无障碍功能事件。
以下过程描述了在此简单应用中创建的无障碍功能事件的路径:
- 应用的代码在应用打开几秒钟后调用
textView.setText("new text")
。 TextView
创建一个TYPE_WINDOW_CONTENT_CHANGED
AccessibilityEvent
并请求其父级RelativeLayout
发送该事件。- 然后,
RelativeLayout
将事件向上传递给其父级ViewRootImpl
,并请求它将事件发送到框架。 ViewRootImpl
通过调用AccessibilityManager
的sendAccessibilityEvent()
,将事件发送到无障碍功能框架。AccessibilityManager
将事件传递给AccessibilityManagerService
,后者将事件从无障碍功能框架传递到VoiceView中。- 当VoiceView处理
TYPE_WINDOW_CONTENT_CHANGED AccessibilityEvent
时,它会调用事件对象的getSource()
方法。 - 这将触发无障碍功能框架来调用
TextView的createAccessibilityNodeInfo()
方法,这会返回一个包含文本“new text”的AccessibilityNodeInfo
对象。 - 无障碍功能框架随后将
AccessibilityNodeInfo
对象传递到VoiceView。 - 最后,VoiceView意识到
TextView
从“hello world”变为“new text”,如果客户使用线性导航来聆听TextView
的文本,VoiceView将会正确地说出“new text”。
自定义视图
如果您的应用使用自定义视图而不是标准视图,则必须坚持使用这种将小部件的状态告知VoiceView的模式。执行此操作时,请勿尝试将AccessibilityNodeInfo
对象发送到VoiceView,或更新应用中AccessibilityNodeInfo
的本地副本;这些方法将不起作用。
请记住,当您更改自定义小部件的状态时:
应该
- 通过对自定义视图的父项调用
requestSendAccessibilityEvent()
来发送AccessibilityEvent
。 - 确保自定义视图的
createAccessibilityNodeInfo()
函数指向的变量包含更新后的值。VoiceView收到AccessibilityEvent
后会调用createAccessibilityNodeInfo()
。
切忌
- 尝试将
AccessibilityNodeInfo
发送到VoiceView。 - 在
createAccessibilityNodeInfo()
函数之外保留对AccessibilityNodeInfo
对象的引用,然后更新这些对象。VoiceView无法引用这些对象,并且永远不会看到您对这些对象的更新。
在Android文档中,请务必查看一个代码示例,该示例演示了在实现createAccessibilityNodeInfo()
函数时,如何正确使用AccessibilityDelegate
和AccessibilityNodeProvider
类。
设置视图的重要性
为确保正确处理无障碍功能事件,请务必为每个Android视图设置无障碍功能的重要性。
在XML布局中使用android:importantForAccessibility
属性或以编程方式使用View.setImportantForAccessibility
方法,可设置视图的无障碍功能重要性状态。您可以将重要性设置为yes、no、no_hide_descendants
或auto
(默认)。未标记为重要的视图没有相应的无障碍功能节点,此外,框架会删除它们发送的任何无障碍功能事件。
如果您的视图正在发送适当的无障碍功能事件,但VoiceView似乎没有正确响应,请验证视图是否标记为对无障碍功能非常重要。
管理AccessibilityNodeInfo对象
Fire OS和Android无障碍功能的一个重要方面是AccessibilityNodeInfo
对象的管理。当在应用进程中运行的Android无障碍功能框架收到针对特定节点的请求时,框架首先检查节点是否在其缓存中:
- 如果缓存中存在节点,则返回该节点,并且不会调用应用来创建节点。因此,每当有关组件的无障碍功能信息发生变化时,您的应用都必须努力通知框架和辅助技术。否则,框架会将过时的信息返回给辅助技术。
- 要指示节点已更改且不再有效,请发送类型为
AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
的无障碍功能事件。 - 如果节点尚未在缓存中,则可以创建节点,具体取决于它的请求方式。辅助技术的几个可行操作可触发
AccessibilityNodeInfo
对象的创建:- 接收无障碍功能事件并请求其源。
- 请求有效窗口的根节点。
- 请求特定节点的父节点或子节点。
实现实际可访问的后代
本节讨论如何实现实际可访问的后代视图。
创建实际可访问的后代视图
AccessibilityDelegate
和AccessibilityNodeProvider
都可以为不通过后备视图表示的屏幕组件提供无障碍功能。此类组件的一个示例是AOSP屏幕键盘,该键盘的键在画布上绘制。请注意,在实现虚拟节点树时,Android提供的ExploreByTouchHelper
支持库可能无法按预期工作。
应用通过托管节点的视图和虚拟视图ID引用AccessibilityNodeInfo
对象。虚拟视图ID -1 (AccessibilityNodeProvider.HOST_VIEW_ID)
引用主视图本身。创建节点时,您可以使用AccessibilityNodeInfo.addChild()
方法添加虚拟子节点,并指定虚拟子节点的主视图和虚拟视图ID。同样,在创建子节点时,您可以在AccessibilityNodeInfo.setParent()
调用中指定主视图和父虚拟视图ID,从而设置虚拟父节点。
管理实际可访问的后代视图
最初创建虚拟视图时,它们只能通过其ID进行引用,并且没有关联的无障碍功能信息(文本、内容描述等)。当无障碍功能框架请求您的应用创建相应的节点时,将相应的无障碍功能信息输入到AccessibilityNodeInfo
中。因此,请确保您的应用跟踪哪个虚拟视图ID表示自定义小部件的哪个部分。
添加子节点或父节点的ID,框架稍后请求您的应用实际创建这些节点。不要简单地将子节点添加到容器节点。
Fire OS无障碍功能最佳实践
为确保具有无障碍功能的应用提供最佳用户体验,请遵循以下指南:
- AccessibilityNodeInfo文本:
AccessibilityNodeInfo
的文本应只返回对象的屏幕文本。 - 屏幕上项目的标签: 屏幕上的所有重要项目都应具有标签。使用VoiceView进行测试时,确保触摸屏幕上的所有项目,并且听到朗读了正确的描述。如果缺少描述,请将相应的文本或内容描述添加到项目的
AccessibilityNodeInfo
中。 - 内容描述: 对没有屏幕文本的项目使用内容描述(例如,图像的替代文本),或者扩充屏幕文本,为用户提供附加上下文。但是,避免在内容描述中放置过多内容,以免用户无所适从。
- 无障碍功能事件用法: 避免使用
AccessibilityEvent.TYPE_ANNOUNCEMENT
事件类型来描述屏幕上的活动。最好联合使用无障碍功能事件以及对AccessibilityNodeInfo
的相应更改,来传达有关屏幕更改的信息。