Размещение / перекрытие (z-index) вида над другим видом в Android

У меня есть линейный макет, который состоит из изображения и текста, один под другим в линейном макете.

<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>

Некоторые правила могут отсутствовать, чтобы дать представление о том, как выглядит макет. Я хочу еще одно небольшое текстовое представление, скажем, 50dip по длине и ширине, расположенное над изображением, под словом "над". Я имел в виду z-index больше, чем изображение, я хочу разместить его в центре и выше (перекрывая) изображения.

Я хочу знать, как мы можем разместить одно представление над другим с переменным z-индексом (предпочтительно в линейном расположении)?

13 ответов

Решение

Вы не можете использовать LinearLayout для этого, но вы можете использовать FrameLayout, В FrameLayout z-индекс определяется порядком, в котором элементы добавляются, например:

<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>

В этом случае TextView будет нарисован в верхней части ImageView, вдоль нижнего центра изображения.

RelativeLayout работает так же, последнее изображение в относительной компоновке выигрывает.

Изменение порядка розыгрыша

Альтернативой является изменение порядка, в котором представления отрисовываются родителем. Вы можете включить эту функцию из ViewGroup, вызвав setChildrenDrawingOrderEnabled(true) и переопределив getChildDrawingOrder (int childCount, int i).

Пример:

/**
 * 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];
    }
}

Выход:

призвание OrderLayout#setDrawOrder(int) с 0-1-2 приводит к:

Я решил ту же проблему, добавив android:elevation="1dp" на какой вид вы хотите это по другому.

Ты можешь использовать view.setZ(float) начиная с уровня API 21. Здесь вы можете найти больше информации.

Попробуйте это в RelativeLayout:

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

Меня устраивает.

Есть способ использовать LinearLayout. Просто установите для marginTop вашего предыдущего элемента соответствующее отрицательное значение и убедитесь, что элемент, который вы хотите поместить сверху, находится после элемента, который вы хотите расположить ниже в своем 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>

AFAIK, вы не можете сделать это с линейными макетами, вам придется пойти на RelativeLayout.

Я использую это, если вы хотите, чтобы при необходимости на передний план выводился только один вид:

containerView.bringChildToFront(topView);

containerView - это контейнер сортируемых представлений, topView - это вид, который я хочу, чтобы он был самым верхним в контейнере.

для упорядочивания нескольких представлений собирается использовать setChildrenDrawingOrderEnabled(true) и переопределить getChildDrawingOrder(int childCount, int i), как указано выше.

Если вы добавляете представление программно, вы можете использовать yourLayout.addView(view, 1);

где 1 is the index.

Попробуйте это в RelativeLayout:

пример XML:

      <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/todo"
        app:srcCompat="@drawable/ic_offer_close_outline"
        app:tint="@color/colorWhite"
        android:translationZ="999dp" />

пример джава:

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

Использоватьandroid:transformZ. Он также работает с LinearLayout.

Другие вопросы по тегам