¿Cómo traer la vista frente a todo?

130

Tengo actividad y muchos widgets, algunos de ellos tienen animaciones y, debido a las animaciones, algunos de los widgets se mueven (traducen) uno sobre otro. Por ejemplo, la vista de texto se mueve sobre algunos botones. . .

Ahora la cosa es que quiero que los botones estén siempre en el frente. Y cuando la vista de texto se mueve, quiero moverme detrás de los botones.

No puedo lograr esto. Probé todo lo que sé, y la definición definitiva de "bringToFront ()" no funciona.

tenga en cuenta que no quiero controlar el orden z por el orden de colocar el elemento en el diseño porque simplemente no puedo :), el diseño es complejo y no puedo colocar todos los botones al principio del diseño

Lukap
fuente
3
Usé una RelativeLayoutcon la vista "superior" que aparece en último lugar en el XML. Ver stackoverflow.com/a/31340762/1121497
Ferran Maylinch
¿Alguien puede decir el código correspondiente en xml de 'bringToFront'?
Shirish Herwade
Intente usar elevación bottomView = elevación: 1dp y topView = elevación: 2dp en su xml || ViewCompat.setElevation (View, int)
Tlacaelel Ramon Luis

Respuestas:

144

Puede llamar a bringToFront () en la vista que desea ver al frente

Esto es un ejemplo:

    yourView.bringToFront();
Medo Elkamaly
fuente
44
Resultado inesperado: lo usé en un diseño lineal vertical y la vista al frente apareció en la parte inferior ... Por ejemplo, tenía A / B / Cy quería traer Aal frente, así que después de correr a.bringToFront()terminé con un diseño similar B / C / A.
Ferran Maylinch
2
Entonces descubrí LinearLayoutque no se puede usar con bringToFront. Terminé usando a RelativeLayout. Vea mi comentario sobre la pregunta en sí.
Ferran Maylinch
1
¿Alguien puede decir el código correspondiente en xml de 'bringToFront'?
Shirish Herwade
Esto da como resultado el reposicionamiento del elemento que estoy moviendo al frente por cualquier razón. ViewCompat.setTranslationZ(view, 1)funciona perfectamente por otro lado.
Bimde
1
si lo usé en manifiesto android: theme = "@ android: style / Theme.Light.NoTitleBar" en actividad que yourView.bringToFront (); funciona perfectamente, pero usé android: theme = "@ android: style / Theme.AppCompat.Light.NoActionBar" yourView.bringToFront (); no funciona Alguna pista sobre eso.
Rahul
42

He estado buscando en el desbordamiento de la pila para encontrar una buena respuesta y cuando no pude encontrar una, busqué en los documentos.

Nadie parece haberse topado con esta simple respuesta todavía:

ViewCompat.setTranslationZ(view, translationZ);

la traducción predeterminada z es 0.0

shrewdu
fuente
Esa es la posición del elemento en el eje Z en px, también conocido como elevación. setTranslationX movería la vista a lo largo del eje X (izquierda / derecha), setTranslationY a lo largo del eje Y (arriba / abajo). El eje Z es el tercer eje.
xdevs23
¿Qué hay de setZ()? Si recuerdo correctamente, la posición Z de la vista es su elevación más su traducción Z, después de todo.
Gensoukyou1337
2
@ Gensoukyou1337, luego ViewCompat.setZ(view, yourValueInPixels); view.setZ()solo funciona en API 21 y superior.
Johnny Five
1
Código Java 8 comprobado en Android Studio: solo comprueba si SDK_INT> = 21, por lo que para <21 api no tiene ningún efecto.
Vadim
32

Una solución aún más simple es editar el XML de la actividad. Utilizar

android:translationZ=""
Toby
fuente
3
Esto solo es útil en Android API 21 o superior.
isakbob
25

bringToFront()es la forma correcta, pero, TENGA EN CUENTA que debe llamar bringToFront()y invalidate()método en la vista de nivel más alto (debajo de su vista raíz), por ejemplo:

La jerarquía de su vista es:

-RelativeLayout
|--LinearLayout1
|------Button1
|------Button2
|------Button3
|--ImageView
|--LinearLayout2
|------Button4
|------Button5
|------Button6

Entonces, cuando vuelvas a animar tus botones (1-> 6), tus botones estarán debajo (debajo) de ImageView. Para traerlo (arriba) ImageViewdebe llamar bringToFront()y invalidate()método en su LinearLayouts. Entonces funcionará :) ** NOTA: Recuerde configurar android:clipChildren="false"para su diseño de raíz o gradparent_layout de animate-view. Echemos un vistazo a mi código real:

.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:hw="http://schemas.android.com/apk/res-auto"
    android:id="@+id/layout_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/common_theme_color"
    android:orientation="vertical" >

    <com.binh.helloworld.customviews.HWActionBar
        android:id="@+id/action_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dimen_actionbar_height"
        android:layout_alignParentTop="true"
        hw:titleText="@string/app_name" >
    </com.binh.helloworld.customviews.HWActionBar>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/action_bar"
        android:clipChildren="false" >

        <LinearLayout
            android:id="@+id/layout_top"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:gravity="center_horizontal"
            android:orientation="horizontal" >
        </LinearLayout>

        <ImageView
            android:id="@+id/imgv_main"
            android:layout_width="@dimen/common_imgv_height"
            android:layout_height="@dimen/common_imgv_height"
            android:layout_centerInParent="true"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher" />

        <LinearLayout
            android:id="@+id/layout_bottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:gravity="center_horizontal"
            android:orientation="horizontal" >
        </LinearLayout>
    </RelativeLayout>

</RelativeLayout>

Algún código en .java

private LinearLayout layoutTop, layoutBottom;
...
layoutTop = (LinearLayout) rootView.findViewById(R.id.layout_top);
layoutBottom = (LinearLayout) rootView.findViewById(R.id.layout_bottom);
...
//when animate back
//dragedView is my layoutTop's child view (i added programmatically) (like buttons in above example) 
dragedView.setVisibility(View.GONE);
layoutTop.bringToFront();
layoutTop.invalidate();
dragedView.startAnimation(animation); // TranslateAnimation
dragedView.setVisibility(View.VISIBLE);

¡Qué suerte!

Justin
fuente
¿Qué sucede si solo desea colocar el botón 6 sobre la vista de imagen y no los otros botones?
Adam Katz
@ AdamKatz: Creo que debes reorganizarlos en otro nivel. Luego, tráelo en tu camino.
Justin
gracias Estoy tratando de traer solo un elemento de una vista de reciclador encima de una vista, pero dejo los otros elementos debajo, ¡bastante atascado!
Adam Katz
Yo usé lo mismo. Funciona bien con un solo problema que oculta la barra de herramientas.
user2980181
¿Funciona esto con múltiples niveles? Digamos que tengo un ConstraintLayoutque contiene un RelativeLayout, y otro RelativeLayout, ambos son del mismo tamaño que su raíz ConstraintLayout( match_parent). El primero RelativeLayouttiene un Button, y también está detrás (en orden z) del segundo RelativeLayout. ¿Puedo hacer que el Buttonprimero RelativeLayoutaparezca como si estuviera encima de todo, de modo que sea visible y se pueda hacer clic en él View::bringToFront()?
oaskamay
25

Con este código en xml

 android:translationZ="90dp"
Krishna
fuente
3
¿De donde 90dpvino?
Sudhir Khanger
1
Es entrada manual. Puede probar según sus requisitos. 45dp o 135dp o 180dp o 270dp
Krishna
¿No podrías usar 1dp?
Tyler Turnbull
18

Intenta FrameLayout, te da la posibilidad de poner vistas una encima de otra. Puede crear dos LinearLayouts: uno con las vistas de fondo y otro con vistas de primer plano, y combinarlos con FrameLayout. Espero que esto ayude.

Egor
fuente
1
¿Cómo podemos llevarlo a la cima como un diálogo?
Gaurav Arora
@Infinity, puede crear un FragmentDialog para este propósito, o simplemente usar el Theme.Dialog para su Actividad.
Egor
No puedo usar FragmentDialog ya que es incompatible con API 10. En segundo lugar, ya estoy usando un tema para mi aplicación. Hay alguna otra manera ? ¡Lo he usado FrameLayout como dijiste!
Gaurav Arora
@Infinity, puede utilizar la versión de la biblioteca de compatibilidad de FragmentDialog, que está disponible en la API 4.
Egor
8

Si está utilizando ConstraintLayout, simplemente coloque el elemento después de los otros elementos para que quede al frente de los demás.

Fajar Ulin Nuha
fuente
3

Puede haber otra forma de salvar el día. Simplemente inicie un nuevo cuadro de diálogo con el diseño deseado y simplemente muéstrelo. Lo necesito para mostrar loadingView sobre un DialogFragment y esta fue la única forma en que tuve éxito.

Dialog topDialog = new Dialog(this, android.R.style.Theme_Translucent_NoTitleBar);
topDialog.setContentView(R.layout.dialog_top);
topDialog.show();

bringToFront () podría no funcionar en algunos casos como el mío. Pero el contenido del diseño dialog_top debe anular cualquier cosa en la capa ui. Pero de todos modos, esta es una solución fea.

asozcan
fuente
3

Me he enfrentado al mismo problema. La siguiente solución me ha funcionado.

 FrameLayout glFrame=(FrameLayout) findViewById(R.id.animatedView);
        glFrame.addView(yourView);
        glFrame.bringToFront();
        glFrame.invalidate();

La segunda solución es mediante el uso de xml agregando este atributo a la vista xml

android:translationZ=""
Mudassir Khan
fuente
2

Puede usar BindingAdapter así:

@BindingAdapter("bringToFront")
public static void bringToFront(View view, Boolean flag) {
    if (flag) {
        view.bringToFront();
    }
}


  <ImageView
        ...
        app:bringToFront="@{true}"/>
Ahmad Aghazadeh
fuente
0

Necesitas usar framelayout. Y la mejor manera de hacer esto es hacer que la vista sea invisible cuando no se requiere. También debe establecer la posición para cada vista, para que se muevan de acuerdo con la posición correspondiente

Ranjit Mishra
fuente
0

Si está utilizando un LinearLayout, debe llamar myView.bringToFront()y después de llamar parentView.requestLayout()y parentView.invalidate()obligar al padre a volver a dibujar con el nuevo pedido hijo.

Cristian
fuente
0

Intenta usar la elevación en él, algo así como yourview.setElevation(5);

Amitoj
fuente
0

Gracias al usuario de Stack por esta explicación, tengo esto funcionando incluso en Android 4.1.1

((View)myView.getParent()).requestLayout();
myView.bringToFront();

En mi uso dinámico, por ejemplo, hice

public void onMyClick(View v)
     {
     ((View)v.getParent()).requestLayout();
     v.bringToFront();
     }

Y Bamm!

PYK
fuente
-2

Organícelos en el orden que desea mostrar. Supongamos que desea mostrar la vista 1 encima de la vista 2. Luego escriba el código de la vista 2 y luego escriba el código de la vista 1. Si no puede hacer este pedido, llame a bringToFront () a la vista raíz del diseño que desea traer al frente.

Shuvendu Dhal
fuente
-32

Puede establecer la visibilidad en falso de otras vistas.

view1.setVisibility(View.GONE);
view2.setVisibility(View.GONE);
...

o

view1.setVisibility(View.INVISIBLE);
view2.setVisibility(View.INVISIBLE);
...

y establecer

viewN.setVisibility(View.VISIBLE);
teosico
fuente
44
Necesito que todo sea visible, ese no es el problema, el problema es el orden z. Si la viabilidad fuera el problema, sería fácil de resolver. . .
Lukap