Why is my system overlay catching all touches (no interaction with underlying view is possible)

12,832

Solution 1

This worked for me:

WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

Use this LayoutParams when adding the View to the WindowManager, it prevents it from receiving any clicks, it's possible that TYPE_TOAST is sufficient, but I've added flags just to make sure.

Solution 2

I also had the same problem and I fix the problem by set the params.width & params.height. Try this.

params.width = 128;
params.height = 128;

I hope it'll help.

Share:
12,832

Related videos on Youtube

Toni Kanoni
Author by

Toni Kanoni

Updated on September 15, 2022

Comments

  • Toni Kanoni
    Toni Kanoni almost 2 years

    I have a service which starts a system overlay. When the overlay is visible, I want it to be touchable/detect touches, but I want to preserve the interaction with the screen behind it (with behind I mean the underlying activity, next to the overlay for example).

    My overlay is a bitmap/PNG of 128x128px. It gets drawn and when I click it, I receive the TOUCH! log, which is good. But also when I click on any other part of the screen (besides the overlay) I get the TOUCH! log and no interaction with the screen underneath it is possible.

    Here are the parts of my code:

    Main Activity to start the service

    buttonStart.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    // start Service and return to Homescreen
                    Intent i = new Intent(MainActivity.this, MyService.class);
                    startService(i);                
    
                    Intent newActivity = new Intent(Intent.ACTION_MAIN); 
                    newActivity.addCategory(Intent.CATEGORY_HOME);
                    newActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(newActivity);
                }
            });
    

    Service/Show overlay

    @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
    
            myOverlay = new Overlay(MyService.this);
    
            WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 
                    PixelFormat.TRANSLUCENT);
            params.gravity = Gravity.LEFT | Gravity.TOP;
    
            wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            wm.addView(myOverlay, params);
    
            myOverlay.setAnimation(new Waiting(MyService.this, 0, 0));
            myOverlay.postInvalidate();
    
            return super.onStartCommand(intent, flags, startId);
        }
    

    Overlay

    public MyOverlay(Context context) {
            super(context);     
            this.context = context;
    
            setOnTouchListener(new OnTouchListener() {
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    Log.i("TOUCH!", event.getAction() + ", x:"+event.getX()+", y:"+event.getY());
                    return false;
                }
            });
        }
    

    What am I doing wrong? Also tried WindowManager.LayoutParams.TYPE_PHONE instead of WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, but same behaviour.

    I am not using the Flag FLAG_WATCH_OUTSIDE_TOUCH, so why are the touches not registered next to the overlay?

    EDIT

    It seems I've found the problem, but still don't know how to solve it though... The displayed image in the overlay is really small and not the problem, but the overlay itself is full screen (!)

    I added the following log to the Overlay / onTouch() event:

    Log.i("TOUCH!", "View: "+v.toString() +", size="+ v.getWidth()+"/"+v.getHeight());
    

    which then tells me View: package.overlay.myOverlay, size=480/762

    Now I tried to force it not to be full screen by adding the following line in the Service:

        @Override
            public int onStartCommand(Intent intent, int flags, int startId) {
    
                myOverlay = new Overlay(MyService.this);
    //HERE
    myOVerlay.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    
                WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                        WindowManager.LayoutParams.WRAP_CONTENT,
                        WindowManager.LayoutParams.WRAP_CONTENT,
                        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 
                        WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 
                        PixelFormat.TRANSLUCENT);
                params.gravity = Gravity.LEFT | Gravity.TOP;
    
                wm = (WindowManager) getSystemService(WINDOW_SERVICE);
                wm.addView(myOverlay, params);
    
                myOverlay.setAnimation(new Waiting(MyService.this, 0, 0));
                myOverlay.postInvalidate();
    
                return super.onStartCommand(intent, flags, startId);
            }
    

    But it does not help... still myOverlay has the size of 480x762... Why is it that big and how can I get it to have the size of the contained image?

  • marmor
    marmor over 9 years
    I think this is the opposite of what the OP wanted, this makes your view catch all clicks.
  • Sam
    Sam over 9 years
    @marmor, in recent versions of Android, TYPE_SYSTEM_OVERLAY windows can't receive touch events.
  • Daniel F
    Daniel F over 6 years
    LayoutParams.TYPE_TOAST is deprecated for Android O
  • Vlad
    Vlad about 6 years
    params.format = PixelFormat.TRANSLUCENT; also may be helpful