如何在 Oreo 中控制 WindowManager 覆盖优先级?

How to control WindowManager overlay priority in Oreo?

我的应用 OV1 有一个叠加层,它基本上是一个按钮,用户可以在屏幕上四处移动。按下此叠加层时,它会生成第二个叠加层 OV2,其中包含位于 OV1 当前位置周围的多个子按钮。 OV2 还会在存在时通过使用标志 WindowManager.LayoutParams.FLAG_DIM_BEHIND.

使屏幕的其余部分变暗

我在最初实施上述方法时遇到的一个问题是,调光效果覆盖了 OV2 以外的所有内容,包括 OV1,变暗并使其不可点击,这会阻止 OV2 关闭,因为 OV1 是开关按钮。我找到的解决方案是为每个叠加层设置不同的布局参数:

OV1 获得:

params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;

而 OV2 获得:

params.type = WindowManager.LayoutParams.TYPE_PHONE

由于OV1的优先级较高,所以它始终处于OV2之上,因此不受FLAG_DIM_BEHIND的影响,用户可以与OV1进行交互,关闭OV2的子按钮菜单。

这一直运行良好,直到我开始更新应用程序以针对 Android 的 API 27 (Oreo)。作为所需更改的一部分,我不得不将两个叠加层的参数类型更改为 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,因此我无法为 OV1 提供更高的优先级以确保它位于 OV2 之上。是否有替代方法来复制此行为,确保 OV1 保持最顶层覆盖,或者在生成 OV2 时强制它到前台?

虽然我从未为此找到解决方案,但一种解决方法是按预期顺序将叠加层重新附加到 window 管理器(当 TYPE_APPLICATION_OVERLAY 类型的多个视图添加到 window manager,最近的放在最上面),通过调用 removeViewImmediate() 然后调用 addView() 来获取你想要放在最上面的视图。

这不太好,因为用户可以看到叠加层在一瞬间不存在,但在有更好的方法之前,它必须这样做。