8

目标是获得可以立即交互的视图(可以立即单击并且会发生某些事情)。如果视图通常可见且可单击,但被另一个视图/菜单/侧面板悬停,则应将其省略。

语音访问做到这一点。它似乎使用了 Accessibility API。

完美的例子是谷歌地图的底部菜单。当它展开时,下方的“沿路线搜索”按钮仍然可见,但应用程序并未突出显示。


那么我们有什么?

  • 有一个AccessibilityEvent流。最有用的是 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,所以当有事情发生时我们可以得到通知。
  • 使用getSource()我们可以获得触发事件的AccessibilityNodeInfo实例。或者我们可以使用AccessibilityService.getRootInActiveWindow()获取窗口的根。有了它,我们就能够遍历应用程序中的整个层次结构。
  • AccessibilityNodeInfo不提供有关视图 z 顺序的任何信息,因此无法理解上面和下面的内容。
  • 底部菜单在同一个窗口中(它不是模态的)。
  • 如果您在底部菜单展开时尝试单击“沿路线搜索”按钮,底部菜单将折叠。因此,您实际上无法单击它,它位于菜单下方。
  • 我查看了AccessibilityNodeInfo的所有参数,例如isVisibleToUser(), isClickable(), isContextClickable(), isSelected(), isFocusable(), isFocused()isAccessibilityFocused()并且当底部菜单折叠/展开时,按钮具有相同的参数。它对用户可见,可聚焦和可点击。

  • 我研究了隐藏的 API,没有看到任何有用的东西。

我错过了什么?


在此处输入图像描述

4

2 回答 2

3

关键是在AccessibilityService.onAccessibilityEvent()中,树层次结构不是最终的。要获得当前可交互的视图,应延迟调用AccessibilityService.getRootInActiveWindow() 。

于 2019-06-18T15:11:16.457 回答
3

AccessibilityNodeInfo#getDrawingOrder() 可能会对您有所帮助。请注意,您需要进行树遍历以确定什么在什么之上。

仍然存在具有透明视图的极端案例会给您带来麻烦,但这应该可以让您完成 95% 的工作。我们正在为这种情况寻找更好的答案。

于 2019-06-18T23:23:53.213 回答