Umieszczanie / nakładanie (indeks Z) widoku nad innym widokiem w Androidzie


230

Mam układ liniowy, który składa się z podglądu obrazu i tekstu, jeden pod drugim w układzie liniowym.

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

Może brakować niektórych zasad, aby dać wyobrażenie o tym, jak wygląda układ. Chcę inny mały widok tekstu, powiedzmy 50dip długości i szerokości, umieszczony nad widokiem obrazu, przez „ponad” Miałem na myśli indeks Z bardziej niż widok obrazu, chcę to umieścić, pośrodku i powyżej (nakładając się) widoku obrazu.

Chcę wiedzieć, jak możemy umieścić jeden widok nad drugim, z różnym indeksem Z (najlepiej w układzie liniowym)?

Odpowiedzi:


295

Nie możesz do tego użyć LinearLayout, ale możesz użyć FrameLayout. W FrameLayoutindeksie z jest określony przez kolejność dodawania elementów, na przykład:

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

W tym przypadku TextView zostanie narysowany na górze ImageView, wzdłuż dolnej środkowej części obrazu.


Tak, zrobiłem to używając samego układu ramki po przejrzeniu dokumentacji. Dziękuję Ci.
sob.

11
Czy istnieje korzyść z użycia FrameLayout zamiast RelativeLayout?
Ixx

12
FrameLayout nie odnosi się do innych widoków w grupie, po prostu nakłada je na warstwy względem rodzica. RelativeLayout służy bardziej do pozycjonowania względem innych elementów.
Kevin Coppock,

3
Cześć kcoppock mój telefon komórkowy (HDpi) nie przestrzega kolejności Z w układzie ramki, ale mam inną (XHDpi) i przestrzegam tej kolejności, czy wiesz, dlaczego to robisz? Z góry dziękuję! : D
Merlí Escarpenter Pérez

1
Od API 21 / KitKat możesz teraz używać setZ i translationZ; hack FrameLayout nie jest już potrzebny (wreszcie!). To powinna być preferowana odpowiedź dla współczesnych wersji 5.0+: stackoverflow.com/a/29703860/358578
pbarranis

183

3
czy możemy tego również użyć w plikach XML?
Reklamy

2
Szukałem czegoś takiego, aby mój widok zmienił itz zindex podczas animacji tłumaczenia.
DeltaCap019,

Czy możesz znaleźć rozwiązanie dla animacji tłumaczenia?
nAkhmedov

9
bringChildToFront () po prostu zmienia indeks widoku wewnątrz swojego obiektu nadrzędnego
Zar E Ahmer

4
to
psuje

66

RelativeLayout działa w ten sam sposób, wygrywa ostatni obraz w układzie względnym.


14
O ile nie użyjesz wysokości, potrzebujesz również największej wartości.
Sami Kuhmonen,

5
To pytanie zostało zadane i udzielone przed powstaniem wzniesienia. Użycie podniesienia nie rozwiąże problemu, jeśli Twoja aplikacja ma minSdk mniejszy niż Lollipop (w telefonach z wersją wcześniejszą niż Lollipop układ będzie wyglądał źle, jeśli polegasz tylko na podniesieniu) - nadal musisz zwracać uwagę na kolejność układu. Masz jednak rację, że jeśli używasz elewacji na dolnym elemencie - zdecydowanie musisz mieć co najmniej taki sam lub wyższy na górze.
jt-gilkeson

27

Zmiana kolejności losowania

Alternatywą jest zmiana kolejności rysowania widoków przez element nadrzędny. Możesz włączyć tę funkcję w ViewGroup, wywołując setChildrenDrawingOrderEnabled (true) i zastępując getChildDrawingOrder (int childCount, int i) .

Przykład:

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

Wynik:

Wywołanie OrderLayout#setDrawOrder(int)z 0-1-2 powoduje:

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj


Czy wywołujesz funkcję setDrawOrder (i) w funkcji onCreate () działania? Jeśli mam 6 widżetów w swoim pliku XML, czy muszę inicjować każdy wiersz DRAW_ORDERS tablicą 6 liczb (0-5)?
John Ward,

@JohnWard pokazany powyżej układ służy wyłącznie przykładowym celom, możesz zdefiniować własne zachowanie w getChildDrawingOrder ().
Tobrun

Oto powiązany post z bardzo wyraźnym kodem: stackoverflow.com/questions/20524162/framelayout-in-reverse
Robert

20

Możesz użyć, view.setZ(float)zaczynając od poziomu API 21. Tutaj możesz znaleźć więcej informacji.


3
To powinna być teraz preferowana odpowiedź dla API 21 / KitKat / 5.0 lub wyższej. Na szczęście stary hack frameLayout nie jest już wymagany. Osobiście nie rozumiem różnicy między setZ a translationZ, ale ten ostatni jest atrybutem i działał dla mnie pięknie. Dzięki!
pbarranis

W poprzednich apisach możesz także użyć ViewCompat # setZ ().
Ali Yucel Akgul

@AliYucelAkgul, jeśli spojrzysz na dokumenty tutaj , możesz zobaczyć Compatibility: API < 21: No-op . Myślę więc, że to nie zadziała
Vadim Kotov

@VadimKotov, próbowałem w mojej aplikacji i to po prostu działa.
Ali Yucel Akgul

@AliYucelAkgul dobrze, to dziwne. Może błąd w dokumentacji? Czy jesteś w 100% pewien, że działa dla API <21? Mam pomysł, że może zmienić kolejność widoków dla poprzednich interfejsów API, ale nie ma żadnych wymyślnych rzeczy, takich jak elewacja itp.
Vadim Kotov,

14

Rozwiązałem ten sam problem, dodając android:elevation="1dp"do którego widoku chcesz go nad innym. Ale nie może wyświetlić poniżej 5.0 i będzie miał trochę cienia, jeśli możesz to zaakceptować, jest w porządku.

Więc najbardziej poprawne rozwiązanie, które jest @kcoppock powiedział.


7

Spróbuj tego w RelativeLayout:

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

Mi to pasuje.


2
Powinieneś wyjaśnić trochę lepiej. Na przykład gdzie możesz umieścić ten kod?
DevB2F,

Cóż, umieściłem go w metodzie OnCreate (). Każde dodane zdjęcie ma indeks preferencji Z względem dodanych wcześniej. Mam na myśli, że poprzez indeks Z mogę zmienić pozycję następnego za poprzednim.
Rizzo

5

Istnieje sposób użycia LinearLayout. Po prostu ustaw marginTop poprzedniego elementu na odpowiednią wartość ujemną i upewnij się, że element, który chcesz na górze, znajduje się za elementem, który chcesz poniżej w pliku 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>

4

AFAIK, że nie możesz tego zrobić z układami liniowymi, musisz wybrać RelativeLayout .


RelativeLayout nie rozszerza frameLayout, czy jesteś pewien, że zadziała?
ekatz

To będzie. Możesz użyć dowolnego z FrameLayout lub RelativeLayout. Każdy z nich ma inne sposoby umieszczania widoków dzieci. Zapoznaj się z dokumentacją, aby dowiedzieć się więcej o tych układach.
Vincent Mimoun-Prat

to jest najlepsza droga
Albert James Teddy


0

Używam tego, jeśli chcesz, aby w razie potrzeby wyświetlać tylko jeden widok:

containerView.bringChildToFront(topView);

containerView to kontener widoków do posortowania, topView to widok, który chcę mieć jako najwyższy w kontenerze.

dla wielu widoków do aranżacji ma zamiar użyć setChildrenDrawingOrderEnabled (true) i nadpisanie getChildDrawingOrder (int childCount, int i), jak wspomniano powyżej.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.