Reputation: 3105
I have an floating view like Facebook chat buble, but unlike it, my overlay has a EditText and need to be focusable.
Here is my floating view code
//Inflate the floating view layout we created
mFloatingView = LayoutInflater.from(this).inflate(R.layout.floating_widget_layout, null);
//Add the view to the window.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
//Specify the view position
params.gravity = Gravity.TOP | Gravity.START; //Initially view will be added to top-left corner
params.x = 0;
params.y = 100;
//Add the view to the window
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mWindowManager.addView(mFloatingView, params);
It is almost okey but there is a problem. When I create overlay from service, System Back Button not working. If I use FLAG_NOT_FOCUSABLE
System buttons; home, recents and back works as expected. I made some research at SO and find out that it is a security issue so I started to find alternative solutions and found this then changed my code
// Wrapper for intercepting System/Hardware key events
ViewGroup wrapper = new FrameLayout(this) {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
Log.v("Back", "Back Key");
return true;
}
return super.dispatchKeyEvent(event);
}
};
//Inflate the floating view layout we created
mFloatingView = LayoutInflater.from(this).inflate(R.layout.floating_widget_layout, wrapper);
//Add the view to the window.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
//Specify the view position
params.gravity = Gravity.TOP | Gravity.START; //Initially view will be added to top-left corner
params.x = 0;
params.y = 100;
//Add the view to the window
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mWindowManager.addView(mFloatingView, params);
Now I can get back press from my floating view but how can I pass this event(back press) to the foreground app(other app, not mine) ? I found this but it didn't help me
If someone can help me or at least give a clue, I will be appreciate
Summary
I have an overlay view, it needs to be focusable, but back press button not working when it is focusable how I can solve this?
Upvotes: 7
Views: 1942
Reputation: 105
Solution: to intercept KeyEvent
events and use them in WindowManager
you have to use FLAG_NOT_TOUCH_MODAL
which allows to collect them. Unfortunately this flag doesn't let these events further so pressing back button won't trigger its regular function. To get rid of that problem simply remove view added to WindowManager
after running the code that you want to use on back press event.
This solution removes the view which might be an obvious disadvantage in some cases.
Example (works well in Service
):
private void addView() {
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
LayoutInflater li = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
WindowManager.LayoutParams parameters = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT
);
parameters.gravity = Gravity.TOP | Gravity.START;
FrameLayout wrapper = new FrameLayout(this) {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
System.out.println("Back pressed");
// do something
view.setVisibility(View.GONE); // removing view allows back press go through
return super.dispatchKeyEvent(event);
}
return super.dispatchKeyEvent(event);
}
public void onCloseSystemDialogs(String reason) {
if (reason.equals("homekey")) {
System.out.println("Home button pressed");
// do something
}
}
};
View view = li.inflate(R.layout.your_layout, wrapper);
view.requestFocus();
view.setFocusable(true);
view.setFocusableInTouchMode(true);
wm.addView(view, parameters);
}
Upvotes: 0
Reputation: 11
This tutorial seems to have a solution: https://www.geeksforgeeks.org/how-to-make-a-floating-window-application-in-android/
They set FLAG_NOT_FOCUSABLE
initially so that the overlay doesn't interfere with system back function, etc. They set onTouch listener on the EditText and update the flag to FLAG_NOT_TOUCH_MODAL
at that point so that text could be entered.
Upvotes: -1