To create an overlay view, when setting up the LayoutParams
you need to set the type to TYPE_SYSTEM_OVERLAY
and use the flag FLAG_WATCH_OUTSIDE_TOUCH
. This presents a problem because as the Android documentation states:
you will not receive the full down/move/up gesture, only the location of the first down as an ACTION_OUTSIDE
.
In order to receive the full array of touch events you need to use the TYPE_SYSTEM_ALERT
type, but this causes the overlay to take over the screen and stop interaction with other elements. The solution is to use both TYPE_SYSTEM_OVERLAY
and TYPE_SYSTEM_ALERT
and switch between them by changing the type of the LayoutParams
as needed.
This is accomplished by:
- Watch for the
ACTION_OUTSIDE
motion event.
- When it occurs, test if it occured within the overlay.
- If it did, switch the
LayoutParams
type to TYPE_SYSTEM_ALERT
- Once the interaction with the overlay is complete, switch back to
TYPE_SYSTEM_OVERLAY
- Repeat
The one thing to keep in mind is that the ACTION_OUTSIDE
motion event is always passed on to the rest of the elements on the screen. So, for example, if the overlay is on top of a button, that button will also receive the motion event and there is no way to stop it.
Also make sure you add the SYSTEM_ALERT_WINDOW
permission to the mainifest file.
I've posted the complete solution here:
http://www.jawsware.mobi/code_OverlayView/ (UPDATED)
It includes all the source code and a link to download the entire example project.
Update for Android 4.0 - 1/3/2013
To create an overlay view, when setting up the LayoutParams DON'T set the type to TYPE_SYSTEM_OVERLAY
.
Instead set it to TYPE_PHONE
.
Use the following flags:
FLAG_NOT_TOUCH_MODAL
FLAG_WATCH_OUTSIDE_TOUCH
FLAG_NOT_TOUCH_MODAL
<< I found this one to be quite important. Without it, focus is given to the overlay and soft-key (home, menu, etc.) presses are not passed to the activity below.
Also, the previous link (above) has been updated to reflect this update.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…