Android overlay a view ontop of everything?
Simply use RelativeLayout
or FrameLayout
. The last child view will overlay everything else.
Android supports a pattern which Cocoa Touch SDK doesn't: Layout management.
Layout for iPhone means to position everything absolute (besides some strech factors). Layout in android means that children will be placed in relation to eachother.
Example (second EditText will completely cover the first one):
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/root_view">
<EditText
android:layout_width="fill_parent"
android:id="@+id/editText1"
android:layout_height="fill_parent">
</EditText>
<EditText
android:layout_width="fill_parent"
android:id="@+id/editText2"
android:layout_height="fill_parent">
<requestFocus></requestFocus>
</EditText>
</FrameLayout>
FrameLayout
is some kind of view stack. Made for special cases.
RelativeLayout
is pretty powerful. You can define rules like View A has to align parent layout bottom, View B has to align A bottom to top, etc
Update based on comment
Usually you set the content with setContentView(R.layout.your_layout)
in onCreate
(it will inflate the layout for you). You can do that manually and call setContentView(inflatedView)
, there's no difference.
The view itself might be a single view (like TextView
) or a complex layout hierarchy (nested layouts, since all layouts are views themselves).
After calling setContentView
your activity knows what its content looks like and you can use (FrameLayout) findViewById(R.id.root_view)
to retrieve any view int this hierarchy (General pattern (ClassOfTheViewWithThisId) findViewById(R.id.declared_id_of_view)
).
How to create an 'Always on top overlay' in Android
Alright. Heres a piece of code which does the job: (You can change the ImageView to any other thing and use it as an overlay.)
startPowerOverlay()
function:
@SuppressLint("ClickableViewAccessibility")
private void startPowerOverlay(){
// Starts the button overlay.
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
overlayPowerBtn = new ImageView(this);
overlayPowerBtn.setImageResource(R.drawable.REPLACE_ME);
int LAYOUT_FLAG;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// APPLICATION_OVERLAY FOR ANDROID 26+ AS THE PREVIOUS VERSION RAISES ERRORS
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
// FOR PREVIOUS VERSIONS USE TYPE_PHONE AS THE NEW VERSION IS NOT SUPPORTED
LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
}
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
LAYOUT_FLAG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.START;
params.x = 0;
params.y = 100;
params.height = 110;
params.width = 110;
windowManager.addView(overlayPowerBtn, params);
overlayPowerBtn.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
private long latestPressTime = 0;
@Override public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Save current x/y
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
// Check for double clicks.
if (latestPressTime == 0 || latestPressTime + 500 < System.currentTimeMillis()) {
latestPressTime = System.currentTimeMillis();
} else {
// Doubleclicked. Do any action you'd like
}
return true;
case MotionEvent.ACTION_UP:
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(overlayPowerBtn, params);
return true;
}
return false;
}
});
}
on onCreate()
:
// Check for overlay permission. If not enabled, request for it. If enabled, show the overlay
if(Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(context)){
CharSequence text = "Please grant the access to the application.";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.fromParts("package", getPackageName(), null)));
} else {
startPowerOverlay();
}
on onDestroy()
:
if (overlayPowerBtn != null)
windowManager.removeView(overlayPowerBtn);
Hope it helps.
How to create Overlay layout in android
Use RelativeLayout or FrameLayout. The last child view will overlay everything else.
To be sure the overlay view is on top, you can call ViewGroup.bringChildViewToFront()
on the relative layout.
Example:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/root_view">
<EditText
android:layout_width="fill_parent"
android:id="@+id/editText1"
android:layout_height="fill_parent">
</EditText>
<EditText
android:layout_width="fill_parent"
android:id="@+id/editText2"
android:layout_height="fill_parent">
<requestFocus></requestFocus>
</EditText>
</FrameLayout>
In this layout, editText2 will cover the editText1
How would I display one view as an overlay of another?
Use a RelativeLayout
for starters.
You could use the ViewGroup.addView(View child, int index, ViewGroup.LayoutParams params)
or a variant along with ViewGroup.removeView(View view)
or ViewGroup.removeViewAt(int index)
.
This would obviously require you to inflate the views manually using LayoutInflater
but you could keep a global reference to each after inflating and just flip between the two.
Android ConstraintLayout - Put one view on top of another view
Set an elevation on the ProgressBar
; 2dp
seems to work.
android:elevation="2dp"
You could also try setting translationZ
as suggested in the accepted answer to a similar question.
I also came across this answer as an alternative.
Creating a system overlay window (always on top)
This might be a stupid solution. But it works. If you can improve it, please let me know.
OnCreate of your Service: I have used WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
flag. This is the only change in service.
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(getBaseContext(),"onCreate", Toast.LENGTH_LONG).show();
mView = new HUDView(this);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.RIGHT | Gravity.TOP;
params.setTitle("Load Average");
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(mView, params);
}
Now, you will start getting each and every click event. So, you need to rectify in your event handler.
In your ViewGroup touch event
@Override
public boolean onTouchEvent(MotionEvent event) {
// ATTENTION: GET THE X,Y OF EVENT FROM THE PARAMETER
// THEN CHECK IF THAT IS INSIDE YOUR DESIRED AREA
Toast.makeText(getContext(),"onTouchEvent", Toast.LENGTH_LONG).show();
return true;
}
Also you may need to add this permission to your manifest:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Add a view on top of all the Activities
In order to manage the show/view of the view I've used the solution proposed by Gopal.
I've attached onStop and onResume events so that the view is hidden when exiting application.
For the click events, I've realized that the type toast does not respond to click events. Therefore I've changed the type
params.type = WindowManager.LayoutParams.TYPE_TOAST;
to
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
I've to add the following permision too:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Related Topics
Intellij Idea with Junit 4.7 "!!! Junit Version 3.8 or Later Expected:"
Elegant Way to Read File into Byte[] Array in Java
How to Use Okhttp to Upload a File
How to Know Whether I am in a Call on Android
What's a Good Library for Parsing Mathematical Expressions in Java
Android How to Listen for Volume Button Events
Android: Switch Camera When Button Clicked
Understand Arraylist Indexoutofboundsexception in Android
How to Give Images Rounded Corners in Android
How to Allow Users to Check for the Latest App Version from Inside the App
Android Data Binding Using Include Tag
Change Position of Google Maps API's "My Location" Button
Adding Java Annotations at Runtime
How to Trim a File Extension from a String in Java
How to Call Launch() More Than Once in Java