Placing/Overlapping(z-index) a view above another view in android

AndroidAndroid LayoutZ Index

Android Problem Overview


I have a linear layout which consists of imageview and textview , one below another in a linear layout.

<LinearLayout android:orientation="horizontal" ... >
 <ImageView 
     android:id="@+id/thumbnail"
     android:layout_weight="0.8" 
     android:layout_width="0dip"
     android:layout_height="fill_parent">
 </ImageView>
 <TextView 
    android:id="@+id/description"
    android:layout_weight="0.2"
    android:layout_width="0dip"
    android:layout_height="wrap_content">
 </TextView>

Some rules might be missing , this is to give an idea , how layout looks. I want another small text view of say 50dip in length and width , placed over the imageview, by "over" I meant z-index more than imageview , I want to place this , in the center and above(overlapping) the imageview.

I want to know how can we place one view above the other, with varying z-index (preferably in linear layout) ?

Android Solutions


Solution 1 - Android

You can't use a LinearLayout for this, but you can use a FrameLayout. In a FrameLayout, the z-index is defined by the order in which the items are added, for example:

<FrameLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	>
	<ImageView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:src="@drawable/my_drawable"
		android:scaleType="fitCenter"
		/>
	<TextView
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="bottom|center"
		android:padding="5dp"
		android:text="My Label"
		/>
</FrameLayout>

In this instance, the TextView would be drawn on top of the ImageView, along the bottom center of the image.

Solution 2 - Android

Solution 3 - Android

RelativeLayout works the same way, the last image in the relative layout wins.

Solution 4 - Android

Changing the draw order

An alternative is to change the order in which the views are drawn by the parent. You can enable this feature from ViewGroup by calling setChildrenDrawingOrderEnabled(true) and overriding getChildDrawingOrder(int childCount, int i).

Example:

/**
 * Example Layout that changes draw order of a FrameLayout
 */
public class OrderLayout extends FrameLayout {

    private static final int[][] DRAW_ORDERS = new int[][]{
            {0, 1, 2},
            {2, 1, 0},
            {1, 2, 0}
    };

    private int currentOrder;

    public OrderLayout(Context context) {
        super(context);
        setChildrenDrawingOrderEnabled(true);
    }

    public void setDrawOrder(int order) {
        currentOrder = order;
        invalidate();
    }

    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        return DRAW_ORDERS[currentOrder][i];
    }
}

Output:

Calling OrderLayout#setDrawOrder(int) with 0-1-2 results in:

enter image description here enter image description here enter image description here

Solution 5 - Android

You can use view.setZ(float) starting from API level 21. Here you can find more info.

Solution 6 - Android

I solved the same problem by add android:elevation="1dp" to which view you want it over another. But it can't display below 5.0, and it will have a little shadow, if you can accept it, it's OK.

So, the most correct solution which is @kcoppock said.

Solution 7 - Android

Try this in a RelativeLayout:

ImageView image = new ImageView(this);
image.SetZ(float z);

It works for me.

Solution 8 - Android

There is a way to use LinearLayout. Just set the marginTop of your previous element to the corresponding negative value, and make sure the element you want on top is after the element you want below in your XML.

<linearLayout android:orientation="horizontal" ... >
<ImageView 
 android:id="@+id/thumbnail"
 android:layout_weight="0.8" 
 android:layout_width="0dip"
 android:layout_height="fill_parent"
>
</ImageView>
<TextView 
android:id="@+id/description"
android:layout_marginTop="-20dip"
android:layout_weight="0.2"
android:layout_width="0dip"
android:layout_height="wrap_content"
>
</TextView>

Solution 9 - Android

AFAIK you cannot do it with linear layouts, you'll have to go for a RelativeLayout.

Solution 10 - Android

I use this, if you want only one view to be bring to front when needed:

containerView.bringChildToFront(topView);

containerView is container of views to be sorted, topView is view which i want to have as top most in container.

for multiple views to arrange is about to use setChildrenDrawingOrderEnabled(true) and overriding getChildDrawingOrder(int childCount, int i) as mentioned above.

Solution 11 - Android

If you are adding the View programmatically, you can use yourLayout.addView(view, 1);

where 1 is the index.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsatView Question on Stackoverflow
Solution 1 - AndroidKevin CoppockView Answer on Stackoverflow
Solution 2 - AndroiddiyismView Answer on Stackoverflow
Solution 3 - Androidjt-gilkesonView Answer on Stackoverflow
Solution 4 - AndroidTobrunView Answer on Stackoverflow
Solution 5 - AndroidVadim KotovView Answer on Stackoverflow
Solution 6 - AndroidthirtyyuanView Answer on Stackoverflow
Solution 7 - AndroidRizzoView Answer on Stackoverflow
Solution 8 - AndroidTimView Answer on Stackoverflow
Solution 9 - AndroidVincent Mimoun-PratView Answer on Stackoverflow
Solution 10 - AndroidMilan JurkulakView Answer on Stackoverflow
Solution 11 - AndroidAlexander MaslewView Answer on Stackoverflow