170

I have activity and a lot of widgets on it, some of them have animations and because of the animations some of the widgets are moving (translating) one over another. For example the text view is moving over some buttons . . .

Now the thing is I want the buttons to be always on the front. And when the textview is moving I want to move behind the buttons.

I can not achieve this I tried everything I know, and "bringToFront()" definitelly doesn't work.

note I do not want to control the z-order by the order of placing element to layout cause I simply can't :), the layout is complex and I can not place all the buttons at the begging of the layout

6rchid
  • 1,074
  • 14
  • 19
Lukap
  • 31,523
  • 64
  • 157
  • 244

19 Answers19

169

You can call bringToFront() on the view you want to get in the front

This is an example:

    yourView.bringToFront();
Medo Elkamaly
  • 2,508
  • 1
  • 20
  • 15
  • 4
    Unexpected result: I used that in a vertical linear layout and the view bringed to front appeared at the bottom... For example, I had `A / B / C` and wanted to bring `A` to front, so after running `a.bringToFront()` I ended up with a layout like `B / C / A`. – Ferran Maylinch Jul 10 '15 at 11:46
  • 2
    So I found `LinearLayout` can't be used with `bringToFront`. I ended up using a `RelativeLayout`. See my comment on the question itself. – Ferran Maylinch Jul 10 '15 at 14:03
  • 1
    can anyone please tell corresponding code in xml of 'bringToFront' – Shirish Herwade Jun 22 '16 at 10:16
  • This results in re-positioning of the element I'm moving to the front for whatever reason. `ViewCompat.setTranslationZ(view, 1)` works perfectly on the other hand. – Bimde Aug 14 '17 at 21:04
  • 1
    if I used in manifest android:theme="@android:style/Theme.Light.NoTitleBar" in activity than yourView.bringToFront(); works perfectly, but I used android:theme="@android:style/Theme.AppCompat.Light.NoActionBar" yourView.bringToFront(); doesn't work. Any clue on that one. – Rahul Mar 27 '18 at 10:22
  • I am trying to temporarily disable all buttons. I put an overlay view when `bringToFront()` on the overlay view works for disabling but how to `bringToBack()` after in order to re-enable them? – Tim Jun 11 '21 at 17:51
  • Does not work for me – VanessaF Apr 09 '22 at 15:23
87

With this code in xml

 android:translationZ="90dp"
barbsan
  • 3,418
  • 11
  • 21
  • 28
Krishna
  • 1,556
  • 13
  • 21
54

I've been looking through stack overflow to find a good answer and when i couldn't find one i went looking through the docs.

no one seems to have stumbled on this simple answer yet:

ViewCompat.setTranslationZ(view, translationZ);

default translation z is 0.0

John Slegers
  • 45,213
  • 22
  • 199
  • 169
shrewdu
  • 716
  • 6
  • 7
  • That is the position of the element on the Z-axis in px, also known as elevation. setTranslationX would move the view along the X-axis (left/right), setTranslationY along the Y-axis (top/bottom). The Z-axis is the 3rd axis. – xdevs23 Mar 22 '16 at 11:41
  • What about `setZ()`? If I recall correctly, the Z position of the view is its elevation plus its translation Z, after all. – Gensoukyou1337 Jul 27 '16 at 07:27
  • 2
    @Gensoukyou1337, then `ViewCompat.setZ(view, yourValueInPixels);` `view.setZ()` works only on API 21 and higher. – Johnny Five Nov 27 '17 at 13:53
  • 1
    Checked Java 8 code in Android Studio - it only checks if SDK_INT >= 21, so for <21 api it has no effect. – Vadim Oct 09 '18 at 12:11
45

An even simpler solution is to edit the XML of the activity. Use

android:translationZ=""
zondo
  • 19,901
  • 8
  • 44
  • 83
Toby
  • 451
  • 4
  • 2
26

bringToFront() is the right way, but, NOTE that you must call bringToFront() and invalidate() method on highest-level view (under your root view), for e.g.:

Your view's hierarchy is:

-RelativeLayout
|--LinearLayout1
|------Button1
|------Button2
|------Button3
|--ImageView
|--LinearLayout2
|------Button4
|------Button5
|------Button6

So, when you animate back your buttons (1->6), your buttons will under (below) the ImageView. To bring it over (above) the ImageView you must call bringToFront() and invalidate() method on your LinearLayouts. Then it will work :) **NOTE: Remember to set android:clipChildren="false" for your root layout or animate-view's gradparent_layout. Let's take a look at my real code:

.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:hw="http://schemas.android.com/apk/res-auto"
    android:id="@+id/layout_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/common_theme_color"
    android:orientation="vertical" >

    <com.binh.helloworld.customviews.HWActionBar
        android:id="@+id/action_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dimen_actionbar_height"
        android:layout_alignParentTop="true"
        hw:titleText="@string/app_name" >
    </com.binh.helloworld.customviews.HWActionBar>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/action_bar"
        android:clipChildren="false" >

        <LinearLayout
            android:id="@+id/layout_top"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:gravity="center_horizontal"
            android:orientation="horizontal" >
        </LinearLayout>

        <ImageView
            android:id="@+id/imgv_main"
            android:layout_width="@dimen/common_imgv_height"
            android:layout_height="@dimen/common_imgv_height"
            android:layout_centerInParent="true"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher" />

        <LinearLayout
            android:id="@+id/layout_bottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:gravity="center_horizontal"
            android:orientation="horizontal" >
        </LinearLayout>
    </RelativeLayout>

</RelativeLayout>

Some code in .java

private LinearLayout layoutTop, layoutBottom;
...
layoutTop = (LinearLayout) rootView.findViewById(R.id.layout_top);
layoutBottom = (LinearLayout) rootView.findViewById(R.id.layout_bottom);
...
//when animate back
//dragedView is my layoutTop's child view (i added programmatically) (like buttons in above example) 
dragedView.setVisibility(View.GONE);
layoutTop.bringToFront();
layoutTop.invalidate();
dragedView.startAnimation(animation); // TranslateAnimation
dragedView.setVisibility(View.VISIBLE);

GLuck!

GergelyPolonkai
  • 6,230
  • 6
  • 35
  • 69
Justin
  • 4,400
  • 2
  • 32
  • 36
  • what if you only want to bring button 6 above the imageview and not the other buttons? – Adam Katz Mar 03 '17 at 12:07
  • @AdamKatz: I think you must re-organize them into another level fist. Then, bring it in your way. – Justin Mar 04 '17 at 04:09
  • thanks I am trying to bring just one item of a recycler view above a view but leave the other items below it, pretty stuck! – Adam Katz Mar 04 '17 at 19:12
  • I used the same. Its working fine with a single problem that it hides the toolbar. –  May 18 '18 at 09:15
  • Does this work with multiple levels? Let's say I have a `ConstraintLayout` that contains a `RelativeLayout`, and another `RelativeLayout`, both are the same size as its root `ConstraintLayout` (`match_parent`). The first `RelativeLayout` has a `Button`, and is also behind (z-order-wise) the second `RelativeLayout`. Can I make the `Button` in the first `RelativeLayout` to appear as if it were on top of everything, such that it's visible and clickable, using `View::bringToFront()`? – oaskamay Jul 13 '18 at 01:08
20

If you are using ConstraintLayout, just put the element after the other elements to make it on front than the others

Fajar Ulin Nuha
  • 399
  • 2
  • 7
18

Try FrameLayout, it gives you the possibility to put views one above another. You can create two LinearLayouts: one with the background views, and one with foreground views, and combine them using the FrameLayout. Hope this helps.

Egor
  • 39,695
  • 10
  • 113
  • 130
  • 1
    How can we bring it to top just like a dialog ? – Gaurav Arora Dec 05 '12 at 13:15
  • @Infinity, You can create a FragmentDialog for this purpose, or just use the Theme.Dialog for your Activity. – Egor Dec 05 '12 at 13:18
  • I can't use FragmentDialog since its incompatible for API 10. Secondly, I'm already using a theme for my application. Is there any other way ? I've used it FrameLayout just like you said ! – Gaurav Arora Dec 05 '12 at 13:22
  • @Infinity, You can use compatibility library version of FragmentDialog, which is available from API 4. – Egor Dec 05 '12 at 13:26
6

i have faced the same problem. the following solution have worked for me.

 FrameLayout glFrame=(FrameLayout) findViewById(R.id.animatedView);
        glFrame.addView(yourView);
        glFrame.bringToFront();
        glFrame.invalidate();

2nd solution is by using xml adding this attribute to the view xml

android:translationZ=""
Mudassir Khan
  • 1,714
  • 1
  • 20
  • 25
5

You can try to use the bringChildToFront, you can check if this documentation is helpful in the Android Developers page.

Emanuel
  • 89
  • 4
  • 14
3

There can be another way which saves the day. Just init a new Dialog with desired layout and just show it. I need it for showing a loadingView over a DialogFragment and this was the only way I succeed.

Dialog topDialog = new Dialog(this, android.R.style.Theme_Translucent_NoTitleBar);
topDialog.setContentView(R.layout.dialog_top);
topDialog.show();

bringToFront() might not work in some cases like mine. But content of dialog_top layout must override anything on the ui layer. But anyway, this is an ugly workaround.

asozcan
  • 1,370
  • 1
  • 17
  • 24
3

You can use BindingAdapter like this:

@BindingAdapter("bringToFront")
public static void bringToFront(View view, Boolean flag) {
    if (flag) {
        view.bringToFront();
    }
}


  <ImageView
        ...
        app:bringToFront="@{true}"/>
Ahmad Aghazadeh
  • 16,571
  • 12
  • 101
  • 98
2

You can use elevation attribute if your minimum api level is 21. And you can reorder view to the bottom of other views to bring it to front. But if elevation of other views is higher, they will be on top of your view.

Samir Alakbarov
  • 1,120
  • 11
  • 21
2

The order of the overlapping views really depends of 4 things:

  1. The attribute android:elevation which is measured in dp/sp
  2. The attribute android:translationZ which is also measured in dp/sp.
  3. In Constraint Layout, the order in which you put the views in your Component Tree is also the order to be shown.
  4. The programmatically order that you set through methods like view.bringToFront() in your kotlin/java code.

The numerals 1 and 2 compite with each other and take preference over the points 3 and 4: if you set elevation="4dp" for View 1 and translationZ="2dp" for View 2, View 1 will always be on top regardless of the numerals 3 and 4.

1

Thanks to Stack user over this explanation, I've got this working even on Android 4.1.1

((View)myView.getParent()).requestLayout();
myView.bringToFront();

On my dynamic use, for example, I did

public void onMyClick(View v)
     {
     ((View)v.getParent()).requestLayout();
     v.bringToFront();
     }

And Bamm !

PYK
  • 3,674
  • 29
  • 17
0

If you are using a LinearLayout you should call myView.bringToFront() and after you should call parentView.requestLayout() and parentView.invalidate() to force the parent to redraw with the new child order.

Kukic Vladimir
  • 1,010
  • 4
  • 15
  • 22
Cristian
  • 117
  • 1
  • 1
  • 11
0

Arrange them in the order you wants to show. Suppose, you wanna show view 1 on top of view 2. Then write view 2 code then write view 1 code. If you cant does this ordering, then call bringToFront() to the root view of the layout you wants to bring in front.

Shuvendu Dhal
  • 75
  • 2
  • 6
0

Try to use app:srcCompat instead of android:src

georgehardcore
  • 975
  • 14
  • 12
-1

You need to use framelayout. And the better way to do this is to make the view invisible when thay are not require. Also you need to set the position for each and every view,So that they will move according to there corresponding position

Ranjit Mishra
  • 440
  • 4
  • 8
-37

You can set visibility to false of other views.

view1.setVisibility(View.GONE);
view2.setVisibility(View.GONE);
...

or

view1.setVisibility(View.INVISIBLE);
view2.setVisibility(View.INVISIBLE);
...

and set

viewN.setVisibility(View.VISIBLE);
alicanbatur
  • 2,172
  • 1
  • 28
  • 36
thenosic
  • 1,463
  • 2
  • 18
  • 22
  • 6
    I need that all to be visible, that is not the problem, the problem is the z-order. if viability was the problem it would be to easy to solve . . . – Lukap Jul 20 '11 at 12:17