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?
An overlay is one of the primary surfaces for app content. Overlays are different from complications or Tiles, which are glanceable representations of app content. Overlays display more information and support richer interactivity.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With