Cómo crear una IU responsiva con ConstraintLayout Parte de Android Jetpack.

Prueba el estilo de Compose
Jetpack Compose es el kit de herramientas de IU recomendado para Android. Obtén información para trabajar con diseños en Compose.

ConstraintLayout te permite crear diseños grandes y complejos con una jerarquía de vistas plana, sin grupos de vistas anidados. Es similar a RelativeLayout, ya que todas las vistas se presentan según las relaciones entre las vistas secundarias y el diseño superior, pero es más flexible que RelativeLayout y más fácil de usar con el editor de diseño de Android Studio.

Toda la potencia de ConstraintLayout está disponible directamente desde las herramientas visuales del editor de diseño, ya que la API de diseño y el editor de diseño están diseñados específicamente para el otro. Puedes compilar tu diseño con ConstraintLayout por completo arrastrando en lugar de editar el XML.

En esta página, se muestra cómo crear un diseño con ConstraintLayout en Android Studio 3.0 o versiones posteriores. Para obtener más información sobre el editor de diseño, consulta Cómo compilar una IU con un editor de diseño.

Para ver una variedad de diseños que puedes crear con ConstraintLayout, consulta el proyecto de ejemplos de Constraint Layout en GitHub.

Descripción general de las restricciones

Para definir la posición de una vista en ConstraintLayout, agrega al menos una restricción horizontal y una vertical para la vista. Cada restricción representa una conexión o alineación con otra vista, el diseño de nivel superior o una guía invisible. Cada restricción define la posición de la vista a lo largo del eje horizontal o vertical. Cada vista debe tener, como mínimo, una restricción en cada eje, pero a menudo se necesitan más.

Cuando sueltas una vista en el editor de diseño, esta permanece donde la dejas, incluso si no tiene restricciones. Esto es solo para facilitar la edición. Si una vista no tiene restricciones cuando ejecutas tu diseño en un dispositivo, se dibuja en la posición [0,0] (la esquina superior izquierda).

En la Figura 1, el diseño se ve bien en el editor, pero no hay restricción vertical en la vista C. Cuando este diseño se dibuja en un dispositivo, la vista C se alinea horizontalmente con los bordes izquierdo y derecho de la vista A, pero aparece en la parte superior de la pantalla porque no tiene restricción vertical.

Figura 1: El editor muestra la vista C debajo de la A, pero no tiene restricción vertical.

Figura 2: La vista C ahora tiene una restricción vertical debajo de la vista A.

Aunque la falta de una restricción no causa un error de compilación, el editor de diseño indica las restricciones faltantes como un error en la barra de herramientas. Para ver los errores y otras advertencias, haz clic en Show Warnings and Errors . Para ayudarte a evitar la falta de restricciones, el editor de diseño agrega restricciones automáticamente con las funciones Inferir restricciones y conectar automáticamente.

Cómo agregar ConstraintLayout a tu proyecto

Para usar ConstraintLayout en tu proyecto, haz lo siguiente:

  1. Asegúrate de tener el repositorio maven.google.com declarado en el archivo settings.gradle:

    Groovy

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        )
        

    Kotlin

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        }
        
  2. Agrega la biblioteca como una dependencia en el archivo build.gradle de nivel de módulo, como se muestra en el siguiente ejemplo. Es posible que la versión más reciente sea diferente a la que se muestra en el ejemplo.

    Groovy

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha13"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13"
    }
    

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha13")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13")
    }
    
  3. En la barra de herramientas o en la notificación de sincronización, haz clic en Sync Project with Gradle Files.

Ya está todo listo para crear el diseño con ConstraintLayout.

Cómo convertir un diseño

Figura 3: El menú para convertir un diseño en ConstraintLayout.

Para convertir un diseño existente en uno de ConstraintLayout, sigue estos pasos:

  1. Abre tu diseño en Android Studio y haz clic en la pestaña Design en la parte inferior de la ventana del editor.
  2. En la ventana Component Tree, haz clic con el botón derecho en el diseño y selecciona Convert LinearLayout to ConstraintLayout.

Cómo crear un nuevo diseño

Para iniciar un archivo de diseño con restricciones nuevo, sigue estos pasos:

  1. En la ventana Project, haz clic en la carpeta del módulo y selecciona File > New > XML > Layout XML.
  2. Ingresa un nombre para el archivo de diseño y escribe "androidx.constraintlayout.widget.ConstraintLayout" en Root Tag.
  3. Haz clic en Finish.

Cómo agregar o quitar una restricción

Para agregar una restricción, haz lo siguiente:

Video 1: El lado izquierdo de una vista está restringido al lado izquierdo del elemento superior.

  1. Arrastra una vista desde la ventana Palette hasta el editor.

    Cuando agregas una vista en un ConstraintLayout, se muestra en un cuadro de límite con controladores de cambio de tamaño cuadrados en cada esquina y controladores de restricciones circulares en cada lado.

  2. Haz clic en la vista para seleccionarla.
  3. Realiza una de las siguientes acciones:
    • Haz clic en un controlador de restricción y arrástralo hasta un punto de anclaje disponible. Ese punto puede ser el borde de otra vista, el borde del diseño o una guía. Ten en cuenta que, a medida que arrastras el controlador de restricciones, el editor de diseño muestra posibles anclas de conexión y superposiciones azules.
    • Haz clic en uno de los botones Create a connection en la sección Layout de la ventana Attributes, como se muestra en la figura 4.

      Figura 4: La sección Layout de la ventana Attributes te permite crear conexiones.

Cuando se crea la restricción, el editor le otorga un margen predeterminado para separar las dos vistas.

Cuando crees restricciones, recuerda las siguientes reglas:

  • Cada vista debe tener al menos dos restricciones: una horizontal y una vertical.
  • Solo puedes crear restricciones entre un controlador de restricciones y un punto de anclaje que compartan el mismo plano. Un plano vertical (los lados izquierdo y derecho) de una vista puede limitarse solo a otro plano vertical, y las líneas de base solo pueden restringirse a otras líneas de base.
  • Cada controlador de restricción se puede usar para una sola restricción, pero es posible crear varias restricciones desde diferentes vistas hasta el mismo punto de anclaje.

Para borrar una restricción, puedes optar por alguna de las siguientes alternativas:

  • Haz clic en una restricción para seleccionarla y, luego, en Borrar.
  • Ctrl y haz clic (Cmd y clic en macOS) en un ancla de restricción. La restricción se vuelve de color rojo para indicar que puedes hacer clic para borrarla, como se muestra en la figura 5.

    Figura 5: Si ves una restricción de color rojo, puedes hacer clic para borrarla.

  • En la sección Layout de la ventana Attributes, haz clic en un anclaje de restricción, como se muestra en la figura 6.

    Figura 6: Haz clic en un anclaje de restricción para borrarlo.

Video 2: Cómo agregar una restricción opuesta a una existente

Si agregas restricciones opuestas en una vista, las líneas de restricción se enrollan como un resorte para indicar las fuerzas opuestas, como se muestra en el video 2. El efecto es más visible cuando el tamaño de la vista se establece como "Fixed" o "Wrap content", en cuyo caso la vista se centra entre las restricciones. En cambio, si quieres que la vista se estire para cumplir con las restricciones, cambia el tamaño para que coincida con las restricciones. Si deseas mantener el tamaño actual, pero mover la vista para que no esté centrada, ajusta el sesgo de restricciones.

Puedes usar restricciones para lograr diferentes tipos de comportamiento de diseño, como se describe en las siguientes secciones.

Posición superior

Restringe el lado de una vista al borde correspondiente del diseño.

En la Figura 7, el lado izquierdo de la vista está conectado al borde izquierdo del diseño de nivel superior. Puedes definir la distancia desde el borde con margen.

Figura 7: Es una restricción horizontal al elemento superior.

Posición de orden

Define el orden de aparición de dos vistas, ya sea de forma horizontal o vertical.

En la Figura 8, B está restringido a estar siempre a la derecha de A, y C está restringido debajo de A. Sin embargo, estas restricciones no implican alineación, por lo que B puede moverse hacia arriba y hacia abajo.

Figura 8: Una restricción horizontal y vertical.

Alineación

Alinea el borde de una vista con el mismo borde de otra vista.

En la figura 9, el lado izquierdo de B está alineado con el lado izquierdo de A. Si deseas alinear los centros de las vistas, crea una restricción en ambos lados.

Para desplazar la alineación, arrastra la vista desde la restricción hacia adentro. Por ejemplo, en la Figura 10, se muestra la B con una alineación de desplazamiento de 24 dp. El desplazamiento se define por el margen de la vista restringida.

También puedes seleccionar todas las vistas que deseas alinear y, luego, hacer clic en Align en la barra de herramientas para seleccionar el tipo de alineación.

Figura 9: Restricción de alineación horizontal.

Figura 10: Restricción de alineación horizontal con desplazamiento.

Alineación de línea de base

Alinea la línea de base de texto de una vista con la línea de base de texto de otra.

En la figura 11, la primera línea de B está alineada con el texto de A.

Para crear una restricción de modelo de referencia, haz clic con el botón derecho en la vista de texto que deseas restringir y, luego, haz clic en Mostrar línea de base. Luego, haz clic en la línea de base del texto y arrástrala a otra línea de base.

Figura 11: Restricción de alineación de línea de base.

Cómo aplicar una restricción a una guía

Puedes agregar una guía vertical u horizontal que te permita restringir las vistas y que sea invisible para los usuarios de tu app. Puedes posicionar la guía dentro del diseño según las unidades dp o un porcentaje relativo al borde del diseño.

Para crear una guía, haz clic en Guidelines en la barra de herramientas y, luego, en Add Vertical Guideline o Add Horizontal Guideline.

Arrastra la línea punteada para cambiar su posición y haz clic en el círculo en el borde de la guía para activar o desactivar el modo de medición.

Figura 12: Es una vista restringida a un lineamiento.

Cómo aplicar una restricción a una barrera

Al igual que una guía, una barrera es una línea invisible a la que puedes restringir las vistas, excepto que una barrera no define su propia posición. En cambio, la posición de la barrera se mueve según la posición de las vistas que contiene. Esto es útil cuando deseas restringir una vista a un conjunto de vistas en lugar de a una vista específica.

Por ejemplo, en la Figura 13, la vista C está restringida al lado derecho de una barrera. La barrera se establece en el "extremo" (o en el lado derecho, en un diseño de izquierda a derecha) de las vistas A y B. La barrera se mueve según si el lado derecho de la vista A o la vista B se encuentra en el extremo derecho.

Para crear una barrera, sigue estos pasos:

  1. Haz clic en Guidelines en la barra de herramientas y, luego, en Add Vertical Barrier o Add Horizontal Barrier.
  2. En la ventana Component Tree, selecciona las vistas que desees dentro de la barrera y arrástralas al componente de la barrera.
  3. Selecciona la barrera en Component Tree, abre la ventana Attributes y, luego, configura barrierDirection.

Ahora puedes crear una restricción desde otra vista hasta la barrera.

También puedes restringir a la barrera las vistas que están dentro de la barrera. De esta manera, puedes alinear todas las vistas de la barrera entre sí, incluso si no sabes qué vista es la más larga o la más alta.

También puedes incluir una guía dentro de una barrera para garantizar una posición "mínima" de la barrera.

Figura 13: La vista C está restringida a una barrera, que se mueve según la posición y el tamaño de las vistas A y B.

Cómo ajustar el sesgo de restricciones

Cuando agregas una restricción a ambos lados de una vista y el tamaño de la vista de la misma dimensión es "fijo" o "ajuste al contenido", la vista se centra entre las dos restricciones con un sesgo del 50% de forma predeterminada. Para ajustar el sesgo, arrastra el control deslizante de sesgo en la ventana Attributes o arrastra la vista, como se muestra en el video 3.

En cambio, si quieres que la vista se estire para cumplir con las restricciones, cambia el tamaño para "ajustar las restricciones".

Video 3: Ajustar el sesgo de restricciones

Cómo ajustar el tamaño de la vista

Figura 14: Cuando se selecciona una vista, la ventana Attributes incluye controles para 1 de proporción de tamaño, 2 para borrar restricciones, 3 modo de alto o ancho, 4 márgenes y 5 sesgo de restricciones. También puedes destacar restricciones individuales en el editor de diseño haciendo clic en ellas en la lista de restricciones 6.

Puedes usar los controladores de las esquinas para cambiar el tamaño de una vista, pero esto codifica el tamaño (la vista no cambia de tamaño para diferentes contenidos o tamaños de pantalla). Si deseas seleccionar un modo de tamaño diferente, haz clic en una vista y abre la ventana Attributes en el lado derecho del editor.

Cerca de la parte superior de la ventana Attributes, se encuentra el inspector de vistas, que incluye controles para varios atributos de diseño, como se muestra en la figura 14. Esto solo está disponible para vistas en un diseño de restricción.

Para cambiar la forma en que se calculan la altura y el ancho, haz clic en los símbolos indicados con el texto destacado 3 en la Figura 14. Estos símbolos representan el modo de tamaño de la siguiente manera. Haz clic en el símbolo para alternar entre estas opciones de configuración:

  • Corregida: Especifica una dimensión específica en el siguiente cuadro de texto o cambia el tamaño de la vista en el editor.
  • Wrap Content: La vista se expande solo las veces que es necesario para ajustarse a su contenido.
    • layout_constraintWidth
    • Configúralo como true para permitir que la dimensión horizontal cambie para respetar las restricciones. De forma predeterminada, un widget configurado como WRAP_CONTENT no está limitado por restricciones.

  • Match Constraints: La vista se expande tanto como sea posible para cumplir con las restricciones de cada lado, después de tener en cuenta los márgenes de la vista. Sin embargo, puedes modificar ese comportamiento con los siguientes atributos y valores. Estos atributos solo se aplican cuando estableces el ancho de la vista como "Match constraints":
    • layout_constraintWidth_min

      Toma una dimensión en dp para el ancho mínimo de la vista.

    • layout_constraintWidth_max

      Toma una dimensión en dp para el ancho máximo de la vista.

    Sin embargo, si la dimensión determinada tiene una sola restricción, la vista se expande para adaptarse a su contenido. El uso de este modo en el ancho o la altura también te permite establecer una proporción de tamaño.

Establecimiento del tamaño como proporción

Figura 15: La vista está configurada en un aspecto de 16:9, y el ancho se basa en una relación de la altura.

Puedes establecer el tamaño de la vista en una relación, como 16:9, si al menos una de las dimensiones de la vista está configurada como "Match constraints" (0dp). Para habilitar la proporción, haz clic en Toggle Aspect Ratio Constraint (texto destacado 1 en la Figura 14) y, luego, ingresa la relación de width:height en la entrada que aparece.

Si el ancho y la altura están configurados en "Match Constraints", puedes hacer clic en Toggle Aspect Ratio Constraint para seleccionar qué dimensión se basa en una proporción de la otra. El inspector de vistas conecta los bordes correspondientes con una línea continua para indicar qué dimensión se establece como una proporción.

Por ejemplo, si configuras ambos lados para que coincidan con las restricciones, haz clic en Toggle Aspect Ratio Constraint dos veces para establecer el ancho como una relación de la altura. El tamaño total depende de la altura de la vista, que se puede definir de cualquier manera, como se muestra en la figura 15.

Cómo ajustar los márgenes de la vista

Para que tus vistas estén espaciadas uniformemente, haz clic en Margin en la barra de herramientas para seleccionar el margen predeterminado para cada vista que agregues al diseño. Los cambios que realices en el margen predeterminado solo se aplicarán a las vistas que agregues a partir de ese momento.

Puedes controlar el margen de cada vista en la ventana Attributes haciendo clic en el número de la línea que representa cada restricción. En la Figura 14, el texto destacado 4 muestra que el margen inferior está establecido en 16 dp.

Figura 16: El botón Margin de la barra de herramientas

Todos los márgenes que ofrece la herramienta son factores de 8 dp, lo que ayuda a que tus vistas se alineen con las recomendaciones de cuadrícula cuadrada de 8 dp de Material Design.

Cómo controlar grupos lineales con una cadena

Figura 17: Cadena horizontal con dos vistas

Una cadena es un grupo de vistas que están vinculadas entre sí con restricciones de posición bidireccional. Dentro de una cadena, se pueden distribuir las vistas de manera horizontal o vertical.

Figura 18: Ejemplos de cada estilo de cadena.

Las cadenas se pueden diseñar de una de las siguientes maneras:

  1. Spread:Las vistas se distribuyen uniformemente después de que se tienen en cuenta los márgenes. Es el valor predeterminado.
  2. Dispersa en el interior: La primera y la última vista se fijan a las restricciones de cada extremo de la cadena y el resto se distribuyen de manera uniforme.
  3. Ponderado: Cuando la cadena se configura como extendida o extendida, puedes llenar el espacio restante configurando una o más vistas para "coincidir restricciones" (0dp). De forma predeterminada, el espacio se distribuye de manera uniforme entre cada vista configurada como "limitación de coincidencia", pero puedes asignar un peso de importancia a cada vista usando los atributos layout_constraintHorizontal_weight y layout_constraintVertical_weight. Esto funciona de la misma manera que layout_weight en un diseño lineal: la vista con el valor de peso más alto obtiene la mayor cantidad de espacio, y las vistas que tienen el mismo peso obtienen la misma cantidad de espacio.
  4. Empaquetado: Las vistas se agrupan después de que se tienen en cuenta los márgenes. Puedes ajustar el sesgo de toda la cadena (izquierda o derecha, o arriba o abajo) si cambias el sesgo de vista de la "cabeza" de la cadena.

La vista de "cabeza" de la cadena (la vista más a la izquierda en una cadena horizontal (en un diseño de izquierda a derecha) y la vista superior en una cadena vertical) definen el estilo de la cadena en XML. Sin embargo, puedes alternar entre spread, spread into y empaquetado si seleccionas cualquier vista en la cadena y haces clic en el botón de la cadena que aparece debajo de la vista.

Para crear una cadena, haz lo siguiente, como se muestra en el video 4:

  1. Selecciona todas las vistas que se incluirán en la cadena.
  2. Haz clic con el botón derecho en una de las vistas.
  3. Selecciona Cadenas.
  4. Selecciona Center Horizontally o Center Vertically.

Video 4: Creación de una cadena horizontal

A continuación, se incluyen algunos aspectos que debes tener en cuenta cuando usas cadenas:

  • Una vista puede formar parte de una cadena horizontal y vertical, por lo que puedes crear diseños de cuadrícula flexibles.
  • Una cadena funciona correctamente solo si cada extremo de la cadena está restringido a otro objeto en el mismo eje, como se muestra en la figura 14.
  • Aunque la orientación de una cadena es vertical u horizontal, cuando se usa una cadena no se alinean las vistas en esa dirección. A fin de lograr la posición adecuada para cada vista en la cadena, incluye otras restricciones, como restricciones de alineación.

Cómo crear restricciones automáticamente

En lugar de agregar restricciones a cada vista a medida que las colocas en el diseño, puedes mover cada vista a las posiciones que desees en el editor de diseño y, luego, hacer clic en Infer Constraints para crear restricciones automáticamente.

Infer Constraints analiza el diseño a fin de determinar el conjunto de restricciones más efectivo para todas las vistas. Limita las vistas a sus posiciones actuales y proporciona flexibilidad. Es posible que debas realizar ajustes para que el diseño responda como deseas en diferentes tamaños y orientaciones de pantalla.

Autoconnect to Parent es una función aparte que también puedes habilitar. Cuando está habilitada y agregas vistas secundarias a un elemento superior, esta función crea automáticamente dos o más restricciones para cada vista a medida que las agregas al diseño, pero solo cuando es apropiado restringir la vista al diseño superior. La conexión automática no crea restricciones para otras vistas del diseño.

La conexión automática está inhabilitada de manera predeterminada. Para habilitarla, haz clic en Enable Autoconnection to Parent en la barra de herramientas del editor de diseño.

Animaciones de fotogramas clave

Dentro de una ConstraintLayout, puedes animar los cambios en el tamaño y la posición de los elementos mediante ConstraintSet y TransitionManager.

Un ConstraintSet es un objeto liviano que representa las restricciones, los márgenes y el padding de todos los elementos secundarios dentro de una ConstraintLayout. Cuando aplicas un ConstraintSet a un ConstraintLayout que se muestra, el diseño actualiza las restricciones de todos sus elementos secundarios.

Para compilar una animación con ConstraintSet, especifica dos archivos de diseño que actúen como fotogramas clave de inicio y fin para la animación. Luego, puedes cargar un ConstraintSet del segundo archivo de fotogramas clave y aplicarlo al ConstraintLayout que se muestra.

En el siguiente ejemplo de código, se muestra cómo realizar una animación moviendo un solo botón hacia la parte inferior de la pantalla.

// MainActivity.kt

fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.keyframe_one)
    constraintLayout = findViewById(R.id.constraint_layout) // member variable
}

fun animateToKeyframeTwo() {
    val constraintSet = ConstraintSet()
    constraintSet.load(this, R.layout.keyframe_two)
    TransitionManager.beginDelayedTransition()
    constraintSet.applyTo(constraintLayout)
}
// layout/keyframe1.xml
// Keyframe 1 contains the starting position for all elements in the animation
// as well as final colors and text sizes.

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
// layout/keyframe2.xml
// Keyframe 2 contains another ConstraintLayout with the final positions.

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Recursos adicionales

ConstraintLayout se usa en la app de demostración de Sunflower.