Definición del orden Z de vistas de RelativeLayout en Android

226

Me gustaría definir el orden z de las vistas de un RelativeLayout en Android.

Sé que una forma de hacer esto es llamar bringToFront.

¿Hay alguna forma mejor de hacer esto? Sería genial si pudiera definir el orden z en el diseño xml.

hpique
fuente
44
View.bringToFront (); is the anser
Shirish Herwade

Respuestas:

314

La forma más fácil es simplemente prestar atención al orden en que se agregan las Vistas a su archivo XML. Más abajo en el archivo significa más arriba en el eje Z.

Editar: Esto está documentado aquí y aquí en el sitio para desarrolladores de Android. (Gracias @flightplanner)

Steve Haley
fuente
16
Desafortunadamente, esto no siempre es posible cambiar. Por ejemplo, en un diseño relativo, cada elemento solo se puede distribuir con respecto a los definidos previamente en el archivo
Casebash
67
Casebash, no creo que sea necesariamente el caso, solo tiene que usar el "@ + id / your_element_before_its_defined" y luego usar el mismo id en el elemento que defina más adelante. Podría estar equivocado sobre esto, estos diseños son muy difíciles para mí, pero definitivamente tengo la impresión de que funciona.
tjb
77
tjb tiene razón (y me alegro de que lo sea). Use @ + id con la primera mención de la identificación, por ejemplo, layout_above = "@ + id / some_id"
Michiel
3
También puede poner <item type = "id" name = "<your_id>" /> en un archivo xml de valores, y luego puede hacer referencia a él en cualquier lugar.
karl
8
Sé que llego 3 años tarde a la fiesta, pero en respuesta a @hpique, esto está documentado aquí
HexAndBugs
88

Si quieres hacer esto en código puedes hacerlo

View.bringToFront();

ver documentos

QAMAR
fuente
68

Tenga en cuenta que los botones y otros elementos en API 21 y superiores tienen una elevación elevada y, por lo tanto, ignoran el orden xml de los elementos independientemente del diseño principal. Me tomó un tiempo entender eso.

Daniel Wilson
fuente
16
La solución a este error para mí fue llamar a setElevation (1000) en la vista que quiero que se muestre sobre el botón.
fuego en el hoyo
setElevation () requiere API nivel 21
dp2050
21

En Android a partir del nivel 21 de API, los elementos en el archivo de diseño obtienen su orden Z tanto de cómo se ordenan dentro del archivo, como se describe en la respuesta correcta, como de su elevación, un valor de elevación más alto significa que el elemento obtiene un orden Z más alto .

Esto a veces puede causar problemas, especialmente con botones que a menudo aparecen en la parte superior de los elementos que de acuerdo con el orden del XML deben estar debajo de ellos en el orden Z. Para solucionar esto, configure los android:elevationelementos en su XML de diseño para que coincidan con el orden Z que desea lograr.

Si establece una elevación de un elemento en el diseño, comenzará a proyectar una sombra. Si no desea este efecto, puede eliminar la sombra con un código como este:

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

No he encontrado ninguna forma de eliminar la sombra de una vista elevada a través del diseño xml.

lejonl
fuente
1
Como se menciona en los comentarios, puede usar android:elevation="1000dp". Ninguna sombra se representa de esta manera.
Vadim Kotov
15

Encontré los mismos problemas: en un diseño relativo parentView, tengo 2 hijos childView1 y childView2. Al principio, puse childView1 sobre childView2 y quiero que childView1 esté encima de childView2. Cambiar el orden de las opiniones de los niños no resolvió el problema para mí. Lo que funcionó para mí es configurar android: clipChildren = "false" en parentView y en el código que configuré:

childView1.bringToFront();

parentView.invalidate();
Tony Vu
fuente
2
Esto está funcionando, y Android me pone muy triste. child.bringToFront()con parent.invalidate()obras, pero parent.bringChildToFront(child)no. ¿Dónde está la lógica que todos esperamos de un sistema operativo?
Oliver Hausler
Para animar algunas vistas (traducciones en X e Y), probé varias combinaciones para LinearLayout, FrameLayout y RelativeLayout pero siempre hubo problemas (relacionados con superposiciones o tamaños no proporcionales). Finalmente android:clipChildren="false"hizo el truco. ¡Gracias!
JCarlosR
15

Tenga en cuenta que puede usar a view.setZ(float)partir del nivel 21 de API. Aquí puede encontrar más información.

Vadim Kotov
fuente
13

Pensé que agregaría una respuesta desde la introducción de la

android: translationZ

El campo XML cambió las cosas un poco. Las otras respuestas que sugieren correr

childView1.bringToFront();

parentView.invalidate();

están totalmente en EXCEPTO porque este código NO traerá childView1 delante de ninguna vista con un Android codificado: translationZ en el archivo XML. Estaba teniendo problemas con esto, y una vez que eliminé este campo de las otras vistas, bringToFront () funcionó bien.

ThePartyTurtle
fuente
Esto también es cierto para los Android 5'selevation
shelll
5

API 21 tiene view.setElevation(float)incorporado

Usar ViewCompat.setElevation(view, float);para compatibilidad con versiones anteriores

Más métodos ViewCompat.setZ(v, pixels)yViewCompat.setTranslationZ(v, pixels)

Otra forma de recopilar botones o ver la matriz y usar addViewpara agregar a RelativeLayout

Qamar
fuente
1

Puede usar personalizado RelativeLayoutcon redefinido

protected int getChildDrawingOrder (int childCount, int i)

Tenga en cuenta que este método toma el parámetro icomo "qué vista debo dibujar i'th". Así es como ViewPagerfunciona. Establece un orden de dibujo personalizado en conjunción con PageTransformer.

Petrov Dmitrii
fuente
0

Compruebe si tiene alguna elevación en una de las Vistas en XML. Si es así, agregue elevación al otro elemento o elimine la elevación para resolver el problema. A partir de ahí, es el orden de las vistas lo que dicta lo que está por encima del otro.

The Fluffy T Rex
fuente
0

O coloque el botón o las vistas superpuestas dentro de un FrameLayout. Luego, RelativeLayout en el archivo xml respetará el orden de los diseños secundarios a medida que se agregan.

Badr
fuente
0

Puede usar el siguiente ejemplo de código también para lograr lo mismo

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

Esto es compatible con versiones anteriores. Aquí mCardViewhay una vista que debería estar debajo sourceView.

Ankit
fuente