androidoverlayandroid-8.0-oreoandroid-windowmanagerandroid-overlay

How to control WindowManager overlay priority in Oreo?


I have an overlay for my app, OV1, which is basically a button the user can move around on their screen. When this overlay is pressed, it spawns a second overlay, OV2, which contains multiple sub-buttons positioned around OV1's current location. OV2 also dims the rest of the screen while present, by use of the flag WindowManager.LayoutParams.FLAG_DIM_BEHIND.

One issue I had when initially implementing the above, is that the dimming effect was cast over everything that isn't OV2, including OV1, darkening and making it unclickable, which prevents OV2 from being closed as OV1 is the toggle button. The solution I found was setting layout params differently for each overlay:

OV1 gets:

params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;

Whereas OV2 gets:

params.type = WindowManager.LayoutParams.TYPE_PHONE

Since OV1 had higher priority, it always stayed on top of OV2, so it wasn't affected by FLAG_DIM_BEHIND, and the user could interact with OV1 just fine to close the OV2 sub-button menu.

This has always worked fine, until I started updating the app to target Android's API 27 (Oreo). As part of the required changes, I've had to change both overlays' param types to WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, so I lost the ability to give OV1 a higher priority to make sure it stays on top of OV2. Is there an alternate way to replicate this behavior, ensuring OV1 remains the topmost overlay, or forcing it to the foreground whenever OV2 is spawned?


Solution

  • While I never found a solution for this, one workaround is to reattach the overlays to the window manager in the intended order (when several views of type TYPE_APPLICATION_OVERLAY are added to the window manager, the most recent ones go on top), by calling removeViewImmediate() followed by addView() for the view you want to be on top.

    It's not pretty, as the user can see the overlay blink out of existence for a split second, but until there's a better way, it'll have to do.