Android ConstraintLayout: coloque una vista encima de otra vista

6 minutos de lectura

avatar de usuario
adam johns

Estoy tratando de agregar un ProgressBar encima de un Button (ambos están dentro de un ConstraintLayout).

<Button
    android:id="@+id/sign_in_button"
    android:layout_width="280dp"
    android:layout_height="75dp"
    android:layout_marginBottom="75dp"
    android:layout_marginTop="50dp"
    android:text="@string/sign_in"
    android:textColor="@color/white"
    android:textSize="22sp"
    android:textStyle="bold"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/passwordEditText"
    app:layout_constraintVertical_bias="0.0"/>

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toTopOf="@+id/sign_in_button"
    android:layout_marginTop="8dp"
    app:layout_constraintBottom_toBottomOf="@+id/sign_in_button"
    android:layout_marginBottom="8dp"
    app:layout_constraintVertical_bias="0.5"
    android:layout_marginLeft="8dp"
    app:layout_constraintLeft_toLeftOf="@+id/sign_in_button"
    android:layout_marginRight="8dp"
    app:layout_constraintRight_toRightOf="@+id/sign_in_button"/>

Pero incluso después de llamar bringToFront sobre el ProgressBar en onCreatesiempre se queda atrás Button.

ProgressBar progressBar = (ProgressBar)findViewById(R.id.progressBar);
progressBar.bringToFront();

  • esto es tan extraño, traté de jugar un poco con su diseño, incluso invirtiendo la cadena para que la barra de progreso esté restringida al texto de edición y el botón a la barra de progreso, pero el botón parece estar siempre encima de la barra de progreso

    – lelloman

    4 de junio de 2017 a las 6:53

  • ¿Eres capaz de usar un FrameLayout? Pruébelo, sabiendo que en FrameLayout, el índice z viene dado por el orden dentro del diseño (entonces Botón 1.º, Progreso 2.º)

    – razgraf

    4 de junio de 2017 a las 7:27


  • ¿dónde está su contraseña? EditText como lo verifiqué sin la aplicación: layout_constraintTop_toBottomOf=”@+id/passwordEditText” Puedo ver la barra de progreso en la parte superior. ¿Puede proporcionar esa contraseña? EditText

    – Pavana

    4 de junio de 2017 a las 8:08


avatar de usuario
Cheticamp

Establecer una elevación en el ProgressBar; 2dp parece funcionar.

android:elevation="2dp"

También puede intentar configurar translationZ como se sugiere en la respuesta aceptada a una pregunta similar.

También encontré esta respuesta como una alternativa.

  • Pero elevation y translationZ son solo para API> = 21, ¿qué pasa con las API más antiguas?

    – q126y

    9 de julio de 2017 a las 5:15

  • @ q126y No creo que esto se haya convertido en un problema hasta la API 21, por lo que las API más antiguas no deberían necesitar esto. Lo probé en un emulador que ejecuta API 17 y la barra de progreso apareció en la parte superior como se esperaba.

    – Cheticamp

    9 de julio de 2017 a las 12:39

  • @Cheticamp entonces, ¿cómo manejar esto? AS advierte que solo funciona con el nivel de API 21 y superior.

    – Ajay S.

    22 de noviembre de 2017 a las 15:54

  • @q126y ViewCompat.setTranslationZ(view, 5)

    – Silvia H.

    27 de noviembre de 2017 a las 13:10

  • ViewCompat.setElavation(view, 20f) le ayuda

    – sagus_helgy

    26 de julio de 2018 a las 9:23


avatar de usuario
ishan fernando

Necesitamos usar Android: elevación para controlar esto.

android:elevation="10dp"

Este atributo de elevación solo funciona en el nivel API> = 21. Pero por debajo de eso, se comportará normalmente. Si agregamos Progreso debajo de la vista Botón, muestra la vista que está en la parte inferior en la parte superior de la otra vista.

avatar de usuario
Cristán

Simplemente puede definir la vista que desea en la parte superior después de la que debería aparecer debajo.

Con los botones, tenga en cuenta que su elevación se rige por su stateListAnimator. El stateListAnimator de Widget.MaterialComponents.Button tiene una elevación predeterminada de @dimen/mtrl_btn_elevation (2dp). Entonces, si desea mostrar una vista en la parte superior de un Botón, debe tener una elevación de al menos 2dp.

  • ¿Cómo se asegura de que el xml pueda reorganizarse accidentalmente?

    – Ram Prasad Bismil

    23 mayo 2019 a las 19:56

  • @Cristan, es mejor proporcionar un fragmento de código o un ejemplo. Gracias

    – blueware

    17 de junio de 2019 a las 8:35

  • me pregunto porque ProgressBar no está encima de la Button a pesar de ProgressBar se define después Button en la pregunta

    – Michael Osofsky

    21 de junio de 2019 a las 20:46

  • Pensé que esto también era cierto, pero no importa dónde coloque una vista de imagen en el orden del diseño de restricción, siempre aparece detrás de un botón

    – behelit

    23 de junio de 2020 a las 3:04

  • Finalmente descubrí por qué esto no parece funcionar para los botones. He actualizado mi respuesta para reflejar esto.

    – Cristán

    29 de enero de 2021 a las 11:35


En el diseño de restricciones, debe usar

traduccionz

superior a la vista que desea a continuación.

A pesar de que android:elevation="4dp" o traslationz funcionará, pero para ese nivel de API debería ser al menos 21. Si por alguna razón no puede hacerlo, asegúrese de que la vista que desea en la parte superior se mencione después de otras vistas. Por ejemplo, si quiero la barra de progreso encima de ImageView:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ImageActivity">

<ImageView
   android:id="@+id/image_view"
   android:layout_width="0dp"
   android:layout_height="0dp"
   app:layout_constraintBottom_toBottomOf="parent"
   app:layout_constraintDimensionRatio="6:4"
   app:layout_constraintEnd_toEndOf="parent"
   app:layout_constraintStart_toStartOf="parent"
   app:layout_constraintTop_toTopOf="parent" />

<ProgressBar
   android:id="@+id/progress_bar"
   style="?android:attr/progressBarStyle"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   app:layout_constraintBottom_toBottomOf="parent"
   app:layout_constraintEnd_toEndOf="parent"
   app:layout_constraintStart_toStartOf="parent"
   app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

El uso de la elevación funciona, pero tiene algunas limitaciones, como que requiere un nivel de API 21+ y también si la elevación es menor (en mi caso, fue 2dp), la vista se vuelve invisible mientras se hace un clic largo, por lo tanto, puede usar un truco simplemente reemplazar el botón con “Ver” o “TextView” puedes hacer todo con estas vistas que se pueden hacer con buttonView

Respuesta actualizada para Android Sutdio 3.5:

En el editor de diseño actualizado, ahora es mucho más fácil elegir qué vista estará al frente, como se demuestra en las notas de la versión de Android Studio.

.. Además, una superposición azul ahora resalta el objetivo de la restricción. Este resaltado es particularmente útil cuando se intenta restringir a un componente que se superpone con otro.

https://developer.android.com/studio/releases

Aún más fácil, si arrastra la Vista hacia arriba (copiar y pegar o desde el Árbol de componentes en el editor de diseño) tendrá una prioridad más baja (por lo que estará detrás de las otras vistas)

¿Ha sido útil esta solución?