Definizione dell'ordine Z delle viste di RelativeLayout in Android


226

Vorrei definire l'ordine z delle visualizzazioni di un RelativeLayout in Android.

So che un modo per farlo è chiamare bringToFront.

Esiste un modo migliore per farlo? Sarebbe bello se potessi definire l'ordine z nel layout xml.


4
View.bringToFront (); è la
risposta

Risposte:


314

Il modo più semplice è semplicemente prestare attenzione all'ordine in cui le viste vengono aggiunte al tuo file XML. Più in basso nel file significa più in alto nell'asse Z.

Modifica: questo è documentato qui e qui sul sito degli sviluppatori Android. (Grazie @flightplanner)


16
Questo purtroppo non è sempre possibile cambiare. Ad esempio, in un layout relativo, ogni elemento può essere disposto solo rispetto a quelli precedentemente definiti nel file
Casebash

67
Casebash, non penso che sia necessariamente il caso in cui devi solo usare "@ + id / your_element_before_its_defined" e quindi usare lo stesso id nell'elemento che definirai in seguito. Potrei sbagliarmi su questo, questi layout sono molto difficili per me, ma ho sicuramente l'impressione che funzioni.
martedì

7
tjb ha ragione (e sono contento che lo sia). Usa @ + id con la prima menzione dell'id, ad esempio layout_above = "@ + id / some_id"
Michiel

3
Puoi anche inserire <item type = "id" name = "<your_id>" /> in un file xml dei valori, quindi puoi fare riferimento ovunque.
karl

8
So di essere in ritardo di circa 3 anni alla festa, ma in risposta a @hpique, questo è documentato qui
HexAndBugs


68

Si noti che i pulsanti e altri elementi in API 21 e versioni successive hanno un'elevazione elevata e pertanto ignorano l'ordine xml degli elementi indipendentemente dal layout principale. Mi ci è voluto un po 'per capirlo.


16
la soluzione a questo bug per me è stata quella di chiamare setElevation (1000) sulla vista che voglio essere renderizzata tramite il pulsante.
fuoco nella buca

setElevation () richiede il livello API 21
dp2050

21

In Android a partire dal livello API 21, gli elementi nel file di layout ottengono il loro ordine Z sia dal modo in cui sono ordinati all'interno del file, come descritto nella risposta corretta, sia dalla loro elevazione, un valore di elevazione più elevato significa che l'oggetto ottiene un ordine Z più alto .

Questo a volte può causare problemi, specialmente con pulsanti che appaiono spesso in cima agli elementi che secondo l'ordine dell'XML dovrebbero essere al di sotto di loro nell'ordine Z. Per risolvere questo problema, imposta gli android:elevationelementi nel tuo XML di layout in modo che corrispondano all'ordine Z che desideri raggiungere.

Se imposti un'elevazione di un elemento nel layout, inizierà a proiettare un'ombra. Se non desideri questo effetto, puoi rimuovere l'ombra con il codice in questo modo:

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

Non ho trovato alcun modo per rimuovere l'ombra di una vista elevata attraverso il layout xml.


1
Come menzionato nei commenti, è possibile utilizzare android:elevation="1000dp". Nessuna ombra è resa in questo modo.
Vadim Kotov,

15

Ho riscontrato gli stessi problemi: in un layout relativo parentView, ho 2 figli childView1 e childView2. Inizialmente, ho inserito childView1 sopra childView2 e desidero che childView1 sia in cima a childView2. Cambiare l'ordine delle opinioni dei bambini non ha risolto il problema per me. Quello che ha funzionato per me è impostare Android: clipChildren = "false" su parentView e nel codice che ho impostato:

childView1.bringToFront();

parentView.invalidate();

2
Funziona e Android mi rende così triste. child.bringToFront()con le parent.invalidate()opere, ma parent.bringChildToFront(child)non lo fa. Dov'è la logica che tutti ci aspettiamo da un sistema operativo?
Oliver Hausler,

Per animare alcune viste (traduzioni in X e Y), ho provato diverse combinazioni per LinearLayout, FrameLayout e RelativeLayout ma c'erano sempre problemi (relativi a sovrapposizioni o dimensioni non proporzionali). Finalmente ha android:clipChildren="false"fatto il trucco. Grazie!
JCarlosR,

15

Nota che puoi utilizzare a view.setZ(float)partire dal livello API 21. Qui puoi trovare maggiori informazioni.


13

Ho pensato di aggiungere una risposta dall'introduzione di

Android: translationZ

Il campo XML ha cambiato un po 'le cose. Le altre risposte che suggeriscono di correre

childView1.bringToFront();

parentView.invalidate();

sono totalmente a posto TRANNE che questo codice NON porterà childView1 davanti a nessuna vista con un Android hardcoded: translationZ nel file XML. Ho avuto problemi con questo, e una volta rimosso questo campo dalle altre viste, bringToFront () ha funzionato bene.


questo vale anche per Android 5elevation
shelll

5

L'API 21 ha il view.setElevation(float)build-in

Utilizzare ViewCompat.setElevation(view, float);per compatibilità con le versioni precedenti

Più metodi ViewCompat.setZ(v, pixels)eViewCompat.setTranslationZ(v, pixels)

Un altro modo è possibile raccogliere pulsanti o visualizzare l'array e utilizzare addViewper aggiungere a RelativeLayout




0

Controlla se hai qualche elevazione su una delle viste in XML. In tal caso, aggiungi l'elevazione all'altro oggetto o rimuovi l'elevazione per risolvere il problema. Da lì, è l'ordine dei punti di vista che detta ciò che viene sopra l'altro.


0

Oppure inserisci il pulsante o le viste sovrapposte all'interno di un FrameLayout. Quindi, RelativeLayout nel file xml rispetterà l'ordine dei layout figlio man mano che vengono aggiunti.


0

È possibile utilizzare il seguente codice di esempio anche per ottenere lo stesso

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

Questo è retrocompatibile. Ecco mCardViewuna vista che dovrebbe essere sotto sourceView.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.