Icono del sitio Develou

Añadir Un ConstraintLayout En Android Studio

El ConstraintLayout es un descendiente de ViewGroup, cuyo fin es permitirte posicionar y redimensionar views de forma flexible a partir de una gran variedad de reglas de restricción.

Las restricciones son similares al concepto de posicionamiento relativo del RelativeLayout, no obstante el ConstraintLayout posee muchos más tipos de condicionamientos para crear diseños más libres.

Sumándole a lo anterior, el editor de layouts de Android Studio provee una inmensa cantidad de interacciones visuales para explotar al máximo los atributos del layout.

En este primer tutorial de la guía verás como:


Ejemplo De ConstraintLayout

Comenzaremos la exploración del ConstraintLayout con el diseño para presentar un tutorial de Develou. Esto involucra el posicionamiento del título, descripción, categoría, fecha de publicación, imagen destacada y dos botones:

Puedes descargar el código final del proyecto desde el siguiente botón:


Añadir Un ConstraintLayout En Nuevo Proyecto

Una de las formas más sencillas de incorporar el ConstraintLayout es a través de la creación de un nuevo proyecto y el uso de las plantillas base de actividades en Android Studio.

En nuestro caso procederemos de la siguiente forma:

Paso 1. Abre Android Studio y crea un nuevo proyecto. Selecciona la plantilla Empty Activity para la actividad principal

Paso 2. Nombra al proyecto «ConstraintLayout» y presiona Finish.

Android Studio añadirá automáticamente el artefacto androidx.constraintlayout en su ultima versión como dependencia a build.gradle del módulo:

dependencies {

    //...
    implementation 'androidx.constraintlayout:constraintlayout:ultima-version'
}

Si el proyecto es antiguo y aún no usas este componente, entonces copia y pega la anterior línea en tu archivo.

Verás que el layout creado automáticamente trae consigo como raíz a un ConstraintLayout y un TextView centrado en su interior:

ConstraintLayout creado por Empty Activity

La definición XML del archivo es:

<?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=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Puntos a tener en cuenta:


Editor De Layouts Y ConstraintLayout

Si abres el archivo activity_main.xml y seleccionas la pestaña Design, verás el editor de layouts con dos tipos de superficies: Design y Blueprint.

La superficie Design mostrará el detalle del contenido de los elementos agregados y Blueprint la omitirá.

Adicionalmente, existe una barra de herramientas con múltiples acciones que veremos en los siguientes tutoriales.

Barra de herramientas asociada al ConstrainLayout

Por otro lado, podrás ver las restricciones de posición en la ventana Attributes con el nombre de Constraints:

Añadir Restricciones

Para probar el uso del editor de layouts sobre el ConstraintLayout, creemos restricciones de posicionamiento con el diseño propuesto al inicio.

Veamos:

Paso 1. Ubícate en la ventana Palette y arrastra los views requeridos: 5 TextViews, un ImageView y 2 Buttons.

Al añadir los views, la ventana Component Tree irá mostrándote los nuevos hijos de la jerarquía. En nuestro caso, esta quedaría así:

Paso 2. A partir de los límites de cada view, representados por círculos en los lados, arrastra una línea de conexión hacia otro elemento con el que deseas que sea condicionado.

Por ejemplo, la imagen destacada va en la parte superior, por lo que alineamos sus bordes superior , izquierdo, derecho con el padre:

Esta edición visual añadirá automáticamente los 3 atributos para las restricciones especificadas por la conexión anterior:

<ImageView
    android:id="@+id/post_featured_image"
    android:layout_width="wrap_content"
    android:layout_height="244dp"
    android:contentDescription="@string/featured_image_desc"
    android:src="@drawable/featured_image"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

Ahora veamos como hacerlo con el título. Este debe alinear su borde superior con el borde inferior de la imagen destacada y sus laterales con el padre:

En este caso, el valor para la restricción borde-superior->borde-inferior tomarán el ID de la imagen destacada post_featured_image:

<TextView
    android:id="@+id/post_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Añadir Un ConstraintLayout En Android Studio"
    android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/post_featured_image" />

Intenta añadir las restricciones de los views restantes teniendo en cuenta esta organización:

El diseño final se vería así:

Y la restricciones en la definición XML son:

<?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"
    android:padding="16dp"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/post_featured_image"
        android:layout_width="wrap_content"
        android:layout_height="244dp"
        android:contentDescription="@string/featured_image_desc"
        android:src="@drawable/featured_image"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/post_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Añadir Un ConstraintLayout En Android Studio"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/post_featured_image" />

    <TextView
        android:id="@+id/post_author"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="James Revelo"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
        android:textStyle="bold"
        app:layout_constraintEnd_toStartOf="@+id/post_category"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/post_title" />

    <TextView
        android:id="@+id/post_publish_date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="22/07/2021"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
        app:layout_constraintEnd_toEndOf="@+id/post_author"
        app:layout_constraintStart_toStartOf="@+id/post_author"
        app:layout_constraintTop_toBottomOf="@+id/post_author" />

    <TextView
        android:id="@+id/post_category"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="UI"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
        app:drawableLeftCompat="@drawable/ic_brush"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/post_title" />

    <TextView
        android:id="@+id/post_content"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:scrollbars="vertical"
        android:text="@string/text_content"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
        app:layout_constraintBottom_toTopOf="@+id/next_button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/post_publish_date" />

    <Button
        android:id="@+id/previous_button"
        style="@style/Widget.MaterialComponents.Button.TextButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Anterior"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/next_button"
        style="@style/Widget.MaterialComponents.Button.TextButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Siguiente"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Aunque las restricciones de posición son muy intuitivas, las estudiaremos en más detalle en el siguiente tutorial.


Convertir Layout A ConstraintLayout

También es posible convertir una layout existente en ConstraintLayout. Android Studio limpiará la jerarquía antigua de atributos innecesarios, inferirá restricciones equivalentes al orden anterior (si es posible) y buscará eliminar layouts anidados .

Pongamos como ejemplo una versión del layout del tutorial, donde el elemento raíz es un LinearLayout como se ve a continuación:

En su interior habrán otros dos LinearLayouts anidados para soportar la horizontalidad de la sección del autor y la de botones:

Su definición XML se vería así:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:padding="16dp">

    <ImageView
        android:id="@+id/post_featured_image"
        android:layout_width="wrap_content"
        android:layout_height="244dp"
        android:contentDescription="@string/featured_image_desc"
        android:src="@drawable/featured_image" />

    <TextView
        android:id="@+id/post_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Añadir Un ConstraintLayout En Android Studio"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/post_author"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="James Revelo"
            android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/post_category"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="UI"
            android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
            app:drawableLeftCompat="@drawable/ic_brush" />
    </LinearLayout>

    <TextView
        android:id="@+id/post_publish_date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="22/07/2021"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" />

    <TextView
        android:id="@+id/post_content"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scrollbars="vertical"
        android:text="@string/text_content"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/previous_button"
            style="@style/Widget.MaterialComponents.Button.TextButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Anterior" />

        <Button
            android:id="@+id/next_button"
            style="@style/Widget.MaterialComponents.Button.TextButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Siguiente" />
    </LinearLayout>

</LinearLayout>

Así que los pasos para convertirlo serán:

Paso 1. Ve a la pestaña Design del layout

Paso 2. Ubícate en la ventana Component Tree, luego haz click derecho en el layout raíz y selecciona Convert LinearLayout to ConstraintLayout

Paso 3. Al presionar esta opción, se desplegará una ventana que te permite elegir dos configuraciones:

Si marcas Flatten Layout Hierarchy los layouts anidados serán removidos.

En el caso de Don’t flatten layouts referenced by id from other files evita que se transformen layouts cuya jerarquía tenga atributos android:id referenciados desde tus archivos de código.

Paso 4. Al presionar OK se comenzará el proceso de conversión y podrás ver el resultado final:

La conversión eliminó los dos layouts anidados y los atributos android:layout_weight. Sin embargo no hubo una inferencia de restricciones, por lo que tendremos que añadir los límites para cada view y así desaparezcan los errores.


Tipos De Restricciones

En este tutorial aprendiste varias formas de añadir un ConstraintLayout a tus proyectos Android Studio y el conocimiento básico para crear restricciones de posicionamiento.

No obstante, elementos como márgenes, tamaño, alineamiento, expansión, etc. necesitan ser atendidos. Por ello, el siguiente paso será profundizar en los tipos de restricciones y su representación en el editor de layouts.

Salir de la versión móvil