Definiowanie kolejności widoków RelativeLayout w systemie Android

226

Chciałbym zdefiniować kolejność Z widoków RelativeLayout w Androidzie.

Wiem, że jednym ze sposobów jest dzwonienie bringToFront.

Czy jest na to lepszy sposób? Byłoby wspaniale, gdybym mógł zdefiniować kolejność Z w xml układu.

hpique
źródło
4
View.bringToFront (); jest anser
Shirish Herwade

Odpowiedzi:

314

Najprostszym sposobem jest zwrócenie uwagi na kolejność dodawania widoków do pliku XML. Niższe w pliku oznacza wyżej w osi Z.

Edycja: jest to udokumentowane tu i tutaj na stronie programisty Androida. (Dzięki @flightplanner)

Steve Haley
źródło
16
Niestety nie zawsze można to zmienić. Na przykład w układzie względnym każdy element może być rozłożony tylko w stosunku do elementów uprzednio zdefiniowanych w pliku
Casebash
67
Casebash, nie sądzę, że w takim przypadku koniecznie trzeba użyć „@ + id / your_element_before_its_defined”, a następnie użyć tego samego identyfikatora w elemencie, który zdefiniujesz później. Mogę się mylić, te układy są dla mnie bardzo trudne, ale zdecydowanie mam wrażenie, że to działa.
tjb
7
tjb ma rację (i cieszę się, że ma). Użyj @ + id z pierwszą wzmianką o id, np. Layout_above = "@ + id / some_id"
Michiel,
3
Możesz również umieścić <item type = "id" name = "<yout_id>" /> w pliku XML wartości, a następnie możesz odwoływać się do niego w dowolnym miejscu.
karl
8
Wiem, że spóźniłem się na imprezę około 3 lat, ale w odpowiedzi na @hpique jest to udokumentowane tutaj
HexAndBugs
88

Jeśli chcesz to zrobić w kodzie, możesz to zrobić

View.bringToFront();

zobacz dokumenty

QAMAR
źródło
68

Uwaga: przyciski i inne elementy w API 21 i nowszych mają wysokie rzędne, dlatego ignorują kolejność elementów w xml bez względu na układ nadrzędny. Zajęło mi trochę czasu, żeby to rozgryźć.

Daniel Wilson
źródło
16
rozwiązaniem tego błędu było dla mnie wywołanie setElevation (1000) w widoku, który chcę wyświetlić za pomocą przycisku.
strzelić do dołka
setElevation () wymaga interfejsu API poziomu 21
dp2050
21

W systemie Android, począwszy od interfejsu API poziomu 21, elementy w pliku układu uzyskują swoją kolejność Z zarówno od sposobu, w jaki są uporządkowane w pliku, jak opisano w prawidłowej odpowiedzi, a od ich rzędnej wyższa wartość rzędnej oznacza, że ​​element otrzymuje wyższą kolejność Z .

Może to czasem powodować problemy, szczególnie w przypadku przycisków, które często pojawiają się nad elementami, które zgodnie z kolejnością XML powinny znajdować się poniżej nich w kolejności Z. Aby to naprawić, po prostu ustaw android:elevationelementy w swoim układzie XML, aby pasowały do ​​kolejności Z, którą chcesz osiągnąć.

Jeśli ustawisz rzędną elementu w układzie, zacznie on rzucać cień. Jeśli nie chcesz tego efektu, możesz usunąć cień za pomocą kodu:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   myView.setOutlineProvider(null);
}

Nie znalazłem żadnego sposobu na usunięcie cienia podwyższonego widoku przez xml układu.

lejonl
źródło
1
Jak wspomniano w komentarzach, możesz użyć android:elevation="1000dp". W ten sposób nie jest renderowany cień.
Vadim Kotov
15

Napotkałem te same problemy: w układzie względnym parentView mam 2 dzieci childView1 i childView2. Na początku umieszczam childView1 nad childView2 i chcę, aby childView1 był na szczycie childView2. Zmiana kolejności widoków dzieci nie rozwiązała problemu. Dla mnie zadziałało ustawienie androida: clipChildren = "false" na parentView oraz w ustawionym przeze mnie kodzie:

childView1.bringToFront();

parentView.invalidate();
Tony Vu
źródło
2
To działa, a Android bardzo mnie zasmuca. child.bringToFront()z parent.invalidate()uczynków, ale parent.bringChildToFront(child)tego nie robi. Gdzie jest logika, której wszyscy oczekujemy od systemu operacyjnego?
Oliver Hausler
Aby animować niektóre widoki (tłumaczenia w X i Y), wypróbowałem kilka kombinacji dla LinearLayout, FrameLayout i RelativeLayout, ale zawsze występowały problemy (związane z nakładaniem się lub nieproporcjonalnymi rozmiarami). Wreszcie android:clipChildren="false"załatwił sprawę. Dziękuję Ci!
JCarlosR
15

Pamiętaj, że możesz używać, view.setZ(float)zaczynając od poziomu API 21. Tutaj znajdziesz więcej informacji.

Wadim Kotow
źródło
13

Myślałem, że dodam odpowiedź od czasu wprowadzenia

Android: translationZ

Pole XML zmieniło to trochę. Inne odpowiedzi sugerujące uruchomienie

childView1.bringToFront();

parentView.invalidate();

są całkowicie WYJĄTKOWE, ponieważ ten kod NIE spowoduje wyświetlenia childView1 przed jakimkolwiek widokiem za pomocą wbudowanego Androida: translationZ w pliku XML. Miałem z tym problemy i kiedy usunąłem to pole z innych widoków, bringToFront () działało dobrze.

ThePartyTurtle
źródło
dotyczy to również Androida 5elevation
shelll
5

API 21 ma view.setElevation(float)wbudowane

Użyj ViewCompat.setElevation(view, float);dla kompatybilności wstecznej

Więcej metod ViewCompat.setZ(v, pixels)iViewCompat.setTranslationZ(v, pixels)

Innym sposobem jest zbieranie przycisków lub wyświetlanie tablicy i używanie ich addViewdo dodawania do RelativeLayout

Qamar
źródło
1

Możesz użyć niestandardowego RelativeLayoutz przedefiniowaniem

protected int getChildDrawingOrder (int childCount, int i)

Uważaj - ta metoda przyjmuje param ijako „który widok powinienem narysować i'th”. Tak to ViewPagerdziała. Ustawia niestandardową kolejność rysowania w połączeniu z PageTransformer.

Petrov Dmitrii
źródło
0

Sprawdź, czy masz jakąkolwiek rzędną w jednym z widoków w XML. Jeśli tak, dodaj elewację do drugiego elementu lub usuń elewację, aby rozwiązać problem. Stamtąd kolejność poglądów decyduje o tym, co stoi ponad innymi.

Fluffy T Rex
źródło
0

Lub umieść nakładający się przycisk lub widoki wewnątrz FrameLayout. Następnie RelativeLayout w pliku xml będzie przestrzegać kolejności układów potomnych podczas dodawania.

Badr
źródło
0

Możesz użyć poniższego kodu również do osiągnięcia tego samego

ViewCompat.setElevation(sourceView, ViewCompat.getElevation(mCardView)+1);

Jest to kompatybilne wstecz. Oto mCardViewwidok, który powinien być poniżej sourceView.

Ankit
źródło