Siguiendo el capítulo anterior, vamos a seguir hablando de los layouts, en concreto en el LinearLayout. El Linearlayout es un contenedor que nos permite asignar vistas en fila, ya sean horizontales o verticales.

LinearLayout

Se trata de un layout muy sencillo y práctico, que nos permite apilar vistas de una forma tan eficaz que aún se sigue usando para vistas sencillas y no tan sencillas. Al trabajar con Linearlayout debemos pensar en que son pilas. Este layout tendrá un espacio que le hemos indicado (ya sea un tamaño fijo, match parent o wrap content) y cada una de las vistas se apilará una después de otra. Para poder definir si las queremos apilar vertical u horizontalmente usaremos el atributo android:orientation=»vertical» o android:orientation=»horizontal».

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#A5D6A7" />

    <View
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#C5E1A5" />

    <View
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#E6EE9C" />

    <View
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#FFF59D" />

    <View
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#FFE082" />

    <View
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#FFCC80" />

    <View
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#FFAB91" />
</LinearLayout>

Tenemos aquí una vista muy sencilla, un linear vertical que tiene siete vistas con un alto de 50 dp.

Ejemplo LinearLayout vertical

Si por el contrario cambiamos el atributo orientation del LinearLayout las vistas se apilarían de izquierda a derecha, pero como cada una de las vistas tiene layout_widthmatch_parent solo se verá la primera. Cambiamos el layout_width a 50 dp y el layout_height match_parent.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <View
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:background="#A5D6A7" />

    <View
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:background="#C5E1A5" />

    <View
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:background="#E6EE9C" />

    <View
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:background="#FFF59D" />

    <View
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:background="#FFE082" />

    <View
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:background="#FFCC80" />

    <View
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:background="#FFAB91" />
</LinearLayout>

Ahora sí serán todas nuestras vistas.

Ejemplo LinearLayout horizontal

Pesos

Hasta aquí todo es muy sencillo, así que vamos complicarlo un poco más. Los LinearLayout, al igual que algunos otros layouts nos permiten trabajar con pesos. Los pesos son básicamente porcentajes que nos permiten decirles que ocupen un ancho relativo al porcentaje de la pantalla. Es decir, imaginemos que tenemos 5 vistas en un LinearLayout horizontal. Si les ponemos un ancho de 0 dp y un peso de 1 a cada una de ellas, cada vista ocupará un 20 por cierto del ancho total del LinearLayout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <View
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:background="#E6EE9C" />

    <View
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:background="#FFF59D" />

    <View
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:background="#FFE082" />

    <View
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:background="#FFCC80" />

    <View
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:background="#FFAB91" />
</LinearLayout>

Este sería el código para trabajar con pesos, vamos a ver lo que hemos hecho.

  • Hemos borrado 2 vistas y solo hemos dejado 5, para que se aprecie mejor.
  • Todos los width que trabajan con pesos han sido puestos a 0 dp. Si no hacemos esto no nos funcionarán.
  • Les hemos puesto el mismo pesos a todos, como son 5 cada uno ocupará el 20% del padre (el LinearLayout padre tiene un match_parent, así que abarca toda la pantalla).

Y visualmente quedaría así.

Ejemplo LinearLayout con pesos

Como vemos y a diferencia de la imagen anterior, este si abarca todo el ancho.

También podemos poner pesos distintos para cada vista y así jugar con los porcentajes. En el próximo ejemplo he añadido un peso de 1 a la primera vista y luego las he ido aumentando hasta llegar a 5.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <View
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:background="#E6EE9C" />

    <View
        android:layout_width="0dp"
        android:layout_weight="2"
        android:layout_height="match_parent"
        android:background="#FFF59D" />

    <View
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="match_parent"
        android:background="#FFE082" />

    <View
        android:layout_width="0dp"
        android:layout_weight="4"
        android:layout_height="match_parent"
        android:background="#FFCC80" />

    <View
        android:layout_width="0dp"
        android:layout_weight="5"
        android:layout_height="match_parent"
        android:background="#FFAB91" />
</LinearLayout>

Ejemplo LinearLayout con pesos distintos.

La primera vista que contiene un peso de uno ocupa justo la mitad de la vista que tiene un peso de dos, y así con cada una. La última vista tiene un peso de cinco, lo que significa que ocupará cinco veces más que la primera vista (de peso uno).

Anidamiento

Podemos anidar todo tipo de LinearLayouts, por ejemplo dentro de uno vertical añadir uno horizontal y jugar con pesos y dimensiones distintas.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <View
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#E6EE9C" />

    <View
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:background="#FFF59D" />

    <View
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:background="#FFE082" />

    <View
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="4"
        android:background="#FFCC80" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="5"
        android:orientation="vertical">

        <View
            android:layout_width="match_parent"
            android:background="#C5E1A5"
            android:layout_height="100dp"/>

        <View
            android:layout_width="match_parent"
            android:background="#E6EE9C"
            android:layout_height="100dp"/>

        <View
            android:layout_width="match_parent"
            android:background="#FFF59D"
            android:layout_height="100dp"/>

        <View
            android:layout_width="match_parent"
            android:background="#FFE082"
            android:layout_height="100dp"/>

        <View
            android:layout_width="match_parent"
            android:background="#FFCC80"
            android:layout_height="100dp"/>

    </LinearLayout>
</LinearLayout>

En la última vista horizontal, he cambiado el view por un LinearLayout con una orientación vertical, y dentro he creado 5 vistas con un tamaño fijo de 100 dp.

Ejemplo LinearLayout con anudamientos.

También debemos entender que anidar con pesos no es recomendable porque necesita muchos recursos para pintar la vista.

Con lo que hemos visto ya seríamos capaz de desarrollar vistas mucho más complejas que las que hemos visto hasta ahora. Así que solo nos quedaría hacer una cosa.

Challenge

Es el momento del reto, y como parece que fue bien el reto anterior, voy a complicar este un poco más.

¿Eres capaz de dibujar esta vista?

Reto del capítulo. ¿Puedes dibujar esta vista?

Esta vista ya se complica un poco ¿verdad? A continuación te daré una breve explicación y algunas pistas.

He puesto vista real y vista blueprint para que puedas apreciar la cantidad de vistas que contiene. Son anidamientos de LinearLayouts horizontales y verticales. Mi recomendación es que intentes crear vistas poco a poco, sabes que hay anudamientos, pues crea el primer nivel todo con vistas y luego sustituye la vista que haga falta por otro nivel de LinearLayout.

  • Todas las vistas están hechas con pesos
  • Son 4 LinearLayouts
  • Los colores pueden ser otros, pero si quieres replicarlo son Material 200 y Material 900.

Solución

¿Difícil? Estoy seguro que lo has conseguido, si es así deja un comentario o dime lo que más te ha costado.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <View
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:background="#E6EE9C" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:orientation="vertical">

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#EF9A9A" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#F48FB1" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#CE93D8" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#B39DDB" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#9FA8DA" />

    </LinearLayout>

    <View
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:background="#FFE082" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:orientation="vertical">

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#90CAF9" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#81D4FA" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#80DEEA" />

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="#80CBC4" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">
            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#B71C1C" />
            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#880E4F" />
            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#4A148C" />
            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#0D47A1" />
            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#006064" />
        </LinearLayout>

    </LinearLayout>

</LinearLayout>

¿Quieres la explicación de cómo se ha resuelto? En el capítulo en vídeo lo explicamos más a fondo.