Android : Multi touch and TYPE_SYSTEM_OVERLAY

14,544

Solution 1

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:

  1. Watch for the ACTION_OUTSIDE motion event.
  2. When it occurs, test if it occured within the overlay.
  3. If it did, switch the LayoutParams type to TYPE_SYSTEM_ALERT
  4. Once the interaction with the overlay is complete, switch back to TYPE_SYSTEM_OVERLAY
  5. 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.

Solution 2

Starting from Android 4.x, Android team Android team fixed a potential security problem by adding a new function adjustWindowParamsLw() in which it will add FLAG_NOT_FOCUSABLE, FLAG_NOT_TOUCHABLE and remove FLAG_WATCH_OUTSIDE_TOUCH flags for TYPE_SYSTEM_OVERLAY window.

That's TYPE_SYSTEM_OVERLAY window won't receive any touch event on ICS platform.

Updated: 2016/5/4 TYPE_TOAST cannot receive touch events on Android 4.0~4.3. It's the same as TYPE_SYSTEM_OVERLAY. On Android 4.4+, TYPE_TOAST removed from the excluded list, so you can use TYPE_TOAST to receive touch events on Android 4.4+ devices.

Share:
14,544
Ravs
Author by

Ravs

Updated on June 11, 2022

Comments

  • Ravs
    Ravs almost 2 years

    I am trying to get multiple touch events on a system overlay view, but am only receiving the MotionEvent.ACTION_OUTSIDE event.

    Is there any possible way of getting multiple touch events on a system overlay?

    Any examples or links would be very helpful.

  • Ravs
    Ravs over 12 years
    Thanks for the update Jawsware. But with your logic also I am not able to see multiple touch events on the overlay. I mean if you keep first finger on screen and then second and then third(without lifting previous ones), we should be able to receive touch events(i.e onTouch() should get called). Is it possible anyway?
  • jawsware
    jawsware over 12 years
    You won't receive multi-touch info while in the TYPE_SYSTEM_OVERLAY state. Once you switch to TYPE_SYSTEM_ALERT (i.e. lift your finger after pressing inside the overlay) you should receive multi-touch events. I appended \nPOINTERS: " + event.getPointerCount() to each of the info.setText calls in my sample and the pointer count would increase\decrease as I touched\lifted my fingers. After the first down, I only received move events, but the pointer count still changed.
  • Ravs
    Ravs over 12 years
    But what I want is actually getting multi-touch with TYPE_SYSTEM_OVERLAY. Is that possible anyway?
  • jawsware
    jawsware over 12 years
    I don't see how, because you only receive ACTION_OUTSIDE. You won't receive UP/DOWN/MOVE. The only solution I could come up with is the Touch To Activate...Do Something...A Gesture/Button to Deactivate.
  • Ravs
    Ravs over 12 years
    Yes, you are right Jawsware. We can only receive ACTION_OUTSIDE with a TYPE_SYSTEM_OVERLAY. But is there any way of getting even UP/DOWN/MOVE etc. kind of events on a "TYPE_SYSTEM_OVERLAY" ?
  • jawsware
    jawsware over 12 years
    It seems TYPE_SYSTEM_OVERLAY is not meant to be able to interfere with touch events and as long as the type doesn't change, there doesn't seem to be away intercept touch events.
  • Brian
    Brian about 12 years
    This is helpful! So what are you suggesting that I use instead of FLAG_WATCH_OUTSIDE_TOUCH to achieve the same functionality before Android 4.0. Is there another flag that should be implemented instead?
  • sdyy
    sdyy almost 10 years
    TYPE_PHONE works like as TYPE_SYSTEM_ALERT, it can not click the button under the layout, not like TYPE_SYSTEM_OVERLAY, in Android 4.4....