A la hora de crear el diseño para nuestras actividades es de gran importancia tener en claro que son los Layouts en Android.
Un Layout es un elemento que representa el diseño de la interfaz de usuario de componentes gráficos como una actividad, fragmento o widget.
Ellos se encargan de actuar como contenedores de views para establecer un orden visual, que facilite la comunicación del usuario con la interfaz de la aplicación.
Descargar Proyecto Android Studio De «Crazy Layouts»
Si deseas desbloquear el link de descarga para el proyecto resultante de este tutorial, entonces sigue estas instrucciones:
[sociallocker id=»7121″][/sociallocker]
¿Cómo Crear Un Layout?
Debido a la existencia de los recursos en Android, los layouts pueden ser creados a través de archivos XML o con código Java de forma programática.
Cuando creas un recurso xml para el layout, mantienes por separado una gran cantidad de código de tus clases principales. Lo que aumenta la comprensión de la estructura del proyecto y además reduce la cantidad de tiempo para el diseño de UI.
En cuanto a la creación dinámica de layouts, debes referirte a las clases ViewGroup y View. Un ViewGroup es un elemento visual que contiene a otros views. Por lo que tienes que usar los métodos apropiados para añadir correctamente los hijos y crear el diseño que deseas.
La mayor parte del tiempo usaremos el estilo declarativo con XML para crear nuestras interfaces. No obstante, en algunas ocasiones requeriremos modificar alguna propiedad de los layouts en tiempo real.
Por ejemplo…
Si deseáramos desaparecer un texto de la interfaz que ya no es necesario, deberíamos acudir al estilo programático para deshabilitar la visibilidad de dicho elemento.
Esto quiere decir, que declarar los elementos de la UI en archivos XML es útil para crear todo el aspecto visual que se usará en la app de forma estática.
Pero si los elementos cambian por algún motivo cuando la app está en funcionamiento, entonces se requiere código Java para modificar dinámicamente los elementos de la UI.
Ambos métodos no son excluyentes.
Crear Layouts En Android Studio
Dentro de la estructura de un proyecto en Android Studio existe el directorio res para el almacenamiento de recursos de la aplicación que se está desarrollando.
Las definiciones XML para los layouts se guardan dentro del subdirectorio layout.
Para crear un layout nuevo, solo presiona click derecho y ve a New > Layout resource file.
Normalmente cuando creas un nuevo proyecto en Android Studio con una actividad en blanco, se genera automáticamente un layout. Algo como:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".ActividadPrincipal"> <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
En este caso, tenemos un elemento raíz llamado RelativeLayout
, el cual contiene un texto con ciertas alineaciones establecidas.
Cada recurso del tipo layout debe ser un archivo XML, donde el elemento raíz solo puede ser un ViewGroup
o un View
. Dentro de este elemento puedes incluir hijos que definan la estructura del diseño.
Algunos de los view groups más populares son:
LinearLayout
FrameLayout
RelativeLayout
TableLayout
GridLayout
Cargar layout XML En Android— Al tener definido tu recurso, ya es posible inflar su contenido en la actividad. Para ello usa el método setContentView()
dentro del controlador onCreate()
.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.actividad_principal); }
Es necesario pasar la referencia del layout que existe dentro del archivo R.java. En el código anterior, cargamos un layout llamado actividad_principal.xml.
Atributos De Un Layout
Todas las características de un ViewGroup o un View son representadas a través de atributos que determinan algún aspecto.
Encontrarás atributos para el tamaño, la alineación, padding, bordes, backgrounds, etc.
Cada atributo XML descrito para un componente tiene una referencia en la clase Java que lo representa. Esto quiere decir que al usar un elemento <TextView>
, nos estamos refiriendo a la clase TextView
.
Identificador de un view— Existe un atributo que heredan todos los elementos llamado id
. Este representa un identificador único para cada elemento. Lo que permite obtener una referencia de cada objeto de forma específica. La sintaxis para el id sería la siguiente:
android:id="@+id/nombre_identificador"
Donde el símbolo '@'
indica al parser interno de XML, que comienza un nuevo identificador para traducir. Y el símbolo '+'
declara que dicho id no existe aún. Por ello se da la orden para crear el identificador dentro del archivo R.java a partir del string que proporcionamos.
Obtener view en una actividad con findViewById()— Una vez definido un id para los views que deseas manipular en el código, se usa el método findViewById()
para obtener sus instancias.
Un ejemplo sería obtener la referencia del TextView
que Android Studio incluye dentro de una nueva actividad en blanco. Supongamos que le asignamos un id referenciado con el nombre «texto_hello_world».
<TextView android:id="@+id/texto_hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" />
Y ahora desde nuestra actividad lo obtenemos:
TextView textoHelloWorld = (TextView)findViewById(R.id.texto_hello_world);
La estrategia es sencilla. Simplemente declaras un objeto del tipo que de view que buscas y luego asignas el resultado que produce findViewById()
. Este recibe como parámetro la referencia que se creó dentro de R.java, la cual tiene el mismo nombre del string que usamos.
Importante realizar el casting del view con el tipo deseado, que en el caso anterior era TextView
.
Cuando estés digitando y pongas el punto en R.id.
, verás cómo Android Studio despliega automáticamente todos los identificadores que existen hasta el momento.
Esta lista de acceso rápido filtrará los identificadores cuando escribas una palabra semejante.
El gran número de identificadores extraños que aparecen, hacen parte de recursos previamente definidos en nuestro proyecto que mantienen la compatibilidad de nuestra UI.
Por otro lado, también puedes referirte a identificadores propios del sistema, con la clase android.R
. A medida que vayas leyendo mis siguientes tutoriales de Desarrollo Android, podrás ver algunos usos de estos identificadores.
Al correr la aplicación, el identificador quedará guardado en tu archivo R.java. Si abres y ves su contenido, encontrarás el identificador dentro de la clase anidada id
, con un valor entero único asignado.
Parámetros De Un Layout
Los parámetros de un layout son atributos especiales que determinan como se relacionan los hijos de un ViewGroup
dependiendo de su posición y tamaño.
Estos se escriben de la forma layout_parametro para someter al view en cuestión. Programáticamente se representan como una clase interna llamada ViewGroup.LayoutParams
.
Dependiendo de la jerarquía encontrada en el layout, así mismo se aplican los parámetros:
La ilustración de ejemplo anterior, muestra un layout cuyo elemento raíz es un Linear Layout. Sus tres hijos del nivel 1 deben ajustarse a los parámetros que este les impone.
Uno de los hijos es un Relative Layout, el cual tiene tres hijos. Como ves, cada elemento del segundo nivel está sometido a los parámetros del relative layout.
Dependiendo del ViewGroup
, así mismo será la naturaleza de los parámetros. Pero existen dos que son comunes independientemente del elemento. Estos son layout_width
y layout_height
.
Definir layout_widht y layout_height— Estos parámetros definen el ancho y la altura respectivamente de un cualquier view.
El gran meollo está en que valor usar para ambos. Es posible asignarles medidas absolutas definidas en dps, sin embargo Google recomienda hacerlo cuando sea estrictamente necesario, ya este tipo de medidas pueden afectar la UI en diferentes tipos de pantalla.
Como ayuda de diseño, se nos han proporcionado dos constantes que ajustan automáticamente las dimensiones de un view.
wrap_content
: Ajusta el tamaño al espacio mínimo que requiere el view. En el siguiente ejemplo se ve como un botón ajusta su ancho y alto, la cantidad necesaria para envolver el texto interior.android:layout_width="wrap_content" android:layout_height="wrap_content"
match_parent
: Ajusta el tamaño a las dimensiones máximas que el padre le permita. La siguiente ilustración muestra el mismo botón anterior, solo que asignadomatch_parent
a su parámetrolayout_width
.android:layout_width="match_parent" android:layout_height="wrap_content"
Ejemplo De FrameLayout
Un FrameLayout
es un view group creado para mostrar un solo elemento en pantalla.
Sin embargo puedes añadir varios hijos con el fin de superponerlos, donde el ultimo hijo agregado, es el que se muestra en la parte superior y el resto se pone por debajo en forma de pila.
Para alinear cada elemento dentro del FrameLayout
usa el parámetro android:layout_gravity
.
El parámetro gravitiy
se basa en las posiciones comunes de un view dentro del layout. Se describe con constantes de orientación:
top
: Indica la parte superior del layout.left
: Indica la parte izquierda del layout.right
: Se refiere a la parte derecha del layout.bottom
: Representa el límite inferior del layout.center_horizontal
: Centro horizontal del layout.center_vertical
: Alineación al centro vertical del layout.center
: Es la combinación decenter_horizontal
ycenter_vertical
.
Como se muestra en la ilustración, es posible crear variaciones combinadas, como por ejemplo right + bottom. En código esta combinación puedes representarla con un OR inclusivo.
android:layout_gravity="right|bottom"
Veamos algo práctico.
Paso 1. Ve a Android Studio y crea un nuevo proyecto. Denomínalo «Crazy Layouts» y agrega una nueva actividad en blanco llamada ActividadPrincipal.java.
Crearemos un diseño con tres views dentro de un frame layout. Habrá una imagen de fondo que recubra todo el layout. También una imagen centrada en ambas dimensiones para resaltar una estadística y un botón alineado en la parte inferior que cerraría la información. Todos ellos estarán superpuestos para generar el mensaje.
Paso 2. Abre el archivo res/layout/actividad_principal.xml y copia el siguiente diseño:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ActividadPrincipal"> <Button android:layout_width="match_parent" android:layout_height="60dp" android:text="Saltar" android:id="@+id/boton_saltar" android:layout_gravity="center_horizontal|bottom"/> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/imagen_background" android:layout_gravity="top|center" android:src="@drawable/background_frame_layout" android:scaleType="centerCrop" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imagen_estadistica" android:layout_gravity="center" android:src="@drawable/ejemplo_estadistica" android:padding="16dp" /> </FrameLayout>
Luego de ello refactoriza el nombre del layout a ejemplo_frame_layout.xml. Para ello presiona click derecho en archivo, en seguida ve a Refactor > Rename… y cambia el nombre. También puedes hacerlo empleando la combinación SHIFT+F6.
Paso 3. Corre la aplicación Android para ver el siguiente resultado.
Ejemplo de LinearLayout
Un LinearLayout es un view group que distribuye sus hijos en una sola dimensión establecida. Es decir, o todos organizados en una sola columna (vertical
) o en una sola fila (horizontal
). La orientación puedes elegirla a través del atributo android:orientation
.
Al igual que el FrameLayout
, el LinearLayout
permite asignar una gravedad a cada componente según el espacio que ocupa.
Adicionalmente existe un parámetro llamado android:layout_weight
, el cual define la importancia que tiene un view dentro del linear layout. A mayor importancia, más espacio podrá ocupar.
La anterior ilustración muestra tres views con pesos de 1, 2 y 3 respectivamente. Es evidente que la magnitud de sus alturas corresponde a su preponderancia. Matemáticamente, el espacio disponible total sería la suma de las alturas (6), por lo que 3 representa el 50%, 2 el 33,33% y 1 el 16,66%.
Aunque esto podemos deducirlo por compresión, es posible definir la suma total del espacio con el atributo android:weightSum
. Dependiendo de este valor, los weights serán ajustados.
android:weightSum="6"
Para distribuir todos los elementos sobre el espacio total del layout, puedes usar el atributo height con valor cero.
android:layout_height="0dp" android:layout_weight="3"
Si no lo haces, el relleno del espacio se definirá por las alturas que tú hayas definido, lo que tal vez no complete el espacio total.
Vayamos a la práctica…
Paso 1. Ve a res/layout y crea un nuevo archivo llamado ejemplo_linear_layout.xml y agrega el siguiente código.
Crearemos un diseño de login, donde se muestren campos para digitar el usuario y el password. Además se incorporará un botón de confirmación y un mensaje que pregunte por el olvido de la contraseña. Todos estarán alineados verticalmente sobre un linear layout.
<?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" android:padding="48dp"> <TextView android:id="@+id/texto_conectar" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_gravity="center_horizontal" android:layout_weight="1" android:text="Conectar" android:textAppearance="?android:attr/textAppearanceLarge" /> <EditText android:id="@+id/input_usuario" android:layout_width="match_parent" android:layout_height="0dp" android:layout_gravity="center_horizontal" android:layout_weight="1" android:hint="Correo" /> <EditText android:id="@+id/input_contrasena" android:layout_width="match_parent" android:layout_height="0dp" android:layout_gravity="center_horizontal" android:layout_weight="1" android:ems="10" android:hint="Contraseña" android:inputType="textPassword" /> <Button android:id="@+id/boton_iniciar_sesion" style="?android:attr/buttonStyleSmall" android:layout_width="match_parent" android:layout_height="0dp" android:layout_gravity="center_horizontal" android:layout_weight="1" android:text="Iniciar Sesion" /> <TextView android:id="@+id/texto_olvidaste_contrasena" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_gravity="center_horizontal" android:layout_weight="1" android:gravity="center_vertical" android:text="¿Olvidaste tu constraseña?" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#0E8AEE" /> </LinearLayout>
Paso 2. Modifica el archivo ActividadPrincipal.java cambiando el layout que existe dentro del método setContentView()
por R.layout.ejemplo_linear_layout
.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ejemplo_frame_layout); }
Paso 3. Corre la aplicación y obtén el siguiente resultado.
Ejemplo De RelativeLayout
Este elemento es el más flexible y elaborado de todos los view groups que veremos. El RelativeLayout
permite alinear cada hijo con referencias subjetivas de cada hermano.
¿Qué significa esto?
Con el RelativeLayout
pensaremos en como alinear los bordes de cada view con otros. Imagina en una sentencia como «el botón estará por debajo del texto» o «la imagen se encuentra a la derecha de la descripción».
En ninguno de los casos nos referimos a una posición absoluta o un espacio determinado. Simplemente describimos la ubicación y el framework de Android computará el resultado final.
El ejemplo anterior ilustra como una serie de views forman un diseño irregular. Esto es posible gracias a unos parámetros que determinan como se juntan los bordes de cada uno y en que alineación.
Cada referencia es indicada usando el identificador de cada view. Por ejemplo, el siguiente botón está por debajo de un view con id "editor_nombre"
(se indica con el parámetro layout_below
).
<span class="tag"><Button</span> <span class="atn">...</span> <span class="atn">android:layout_below</span><span class="pun">=</span><span class="atv">"@+id/editor_nombre"</span><span class="tag">/></span>
Veamos algunos de los parámetros del RelativeLayout para definir posiciones:
android:layout_above
: Posiciona el borde inferior del elemento actual con el borde superior del view referenciado con el id indicado.android:layout_centerHorizontal
: Usa true para indicar que el view será centrado horizontalmente con respecto al padre.android:layout_alignParentBottom
: Usa true para alinear el borde inferior de este view con el borde inferior del padre.android:layout_alignStart
: Alinea el borde inicial de este elemento con el borde inicial del view referido porid
.
Ahora probemos un ejemplo…
Paso 1. Crea otro layout dentro de res/layout llamado ejemplo_relative_layout.xml.
Esta vez crearemos un pequeño formulario con cuatro campos de una persona. Se usará un edit text para los nombres y otro para los apellidos. Por debajo tendremos dos spinners que permitirán seleccionar el estado civil y el cargo actual. Todos van alineados dentro de un relative layout
Implementa la siguiente definición:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_horizontal_margin"> <EditText android:id="@+id/input_nombre" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:ems="10" android:hint="Nombres" android:inputType="textPersonName" /> <EditText android:id="@+id/input_apellido" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/input_nombre" android:ems="10" android:hint="Apellidos" android:inputType="textPersonName" /> <TextView android:id="@+id/texto_estado_civil" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/input_apellido" android:layout_marginRight="48dp" android:paddingBottom="8dp" android:paddingTop="16dp" android:text="Estado civil" android:textAppearance="?android:attr/textAppearanceMedium" /> <Spinner android:id="@+id/spinner_estado_civil" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/texto_estado_civil" android:layout_toLeftOf="@+id/spinner_cargo" android:entries="@array/lista_estado_civil" /> <TextView android:id="@+id/texto_cargo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/input_apellido" android:layout_centerHorizontal="true" android:layout_toRightOf="@+id/texto_estado_civil" android:paddingBottom="8dp" android:paddingTop="16dp" android:text="Cargo" android:textAppearance="?android:attr/textAppearanceMedium" /> <Spinner android:id="@+id/spinner_cargo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/texto_cargo" android:layout_alignParentRight="true" android:layout_alignStart="@+id/texto_cargo" android:layout_below="@+id/texto_cargo" android:entries="@array/lista_cargo" /> </RelativeLayout>
Paso 2. Cambia el parámetro de setContentView()
por R.layout.ejemplo_relative_layout
.
Paso 3. Visualiza el resultado.
Ejemplo De TableLayout
Como ya te lo imaginarás, el TableLayout organiza views en filas y columnas de forma tabular.
Para crear las filas se usa el componente TableRow
dentro del TableLayout
. Cada celda es declarada como un view de cualquier tipo (imagen, texto, otro group view, etc.) dentro de la fila. Sin embargo, puedes crear una celda con otro tipo de view. Esto hará que todo el espacio de la fila sea ocupado por el objeto.
El TableRow
trae consigo un parámetro llamado android:layout_column
para asignar la columna a la que pertenece cada celda en su interior. Incluso puedes usar el parámetro weight
para declarar pesos de las celdas.
El ancho de cada columna es definido tomando como referencia la celda más ancha. Pero también podemos definir el comportamiento del ancho de las celdas con los siguientes atributos:
android:shrinkColumns
: Reduce el ancho de la columna seleccionada hasta ajustar la fila al tamaño del padre.android:stretchColumns
: Permite rellenar el espacio vacío que queda en elTableLayout
, expandiendo la columna seleccionada.
A continuación crearemos una prueba.
Paso 1. Crea un nuevo archivo dentro de res/layout con el nombre de ejemplo_table_layout.xml. Esta vez verás el diseño de una factura en forma de tabla. Habrá una columna para los productos y otra para representar el subtotal.
Al final de los ítems pondremos una línea divisoria y por debajo calcularemos la cuenta total.
<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" android:stretchColumns="1"> <TableRow android:background="#128675"> <TextView android:layout_column="0" android:padding="3dip" android:text="Producto" android:textColor="@android:color/white" /> <TextView android:layout_column="2" android:padding="3dip" android:text="Subtotal" android:textColor="@android:color/white" /> </TableRow> <TableRow> <TextView android:layout_column="0" android:padding="3dip" android:text="Jabón de manos x 1" /> <TextView android:layout_column="2" android:gravity="left" android:padding="3dip" android:text="$2" /> </TableRow> <TableRow> <TextView android:layout_column="0" android:padding="3dip" android:text="Shampoo Monster x 1" /> <TextView android:layout_column="2" android:gravity="left" android:padding="3dip" android:text="$10" /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="0" android:padding="3dip" android:text="Pastas Duria x 2" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:gravity="left" android:padding="3dip" android:text="$18" /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="0" android:padding="3dip" android:text="Detergente Limpiadin x 1" /> <TextView android:id="@+id/textView4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:gravity="left" android:padding="3dip" android:text="$13,4" /> </TableRow> <View android:layout_height="2dip" android:background="#FF909090" /> <TableRow> <TextView android:layout_column="1" android:padding="3dip" android:text="Subtotal" android:textColor="#128675" /> <TextView android:id="@+id/textView7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_gravity="left" android:gravity="right" android:padding="3dip" android:text="$43,4" /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="1" android:padding="3dip" android:text="Costo envío" android:textColor="#128675" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_gravity="left" android:gravity="right" android:padding="3dip" android:text="$10" /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="1" android:padding="3dip" android:text="Cupón" android:textColor="#128675" /> <TextView android:id="@+id/textView9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_gravity="left" android:gravity="right" android:padding="3dip" android:text="-$5" /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="1" android:padding="3dip" android:text="Total" android:textColor="#128675" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_gravity="left" android:gravity="right" android:padding="3dip" android:text="$48,4" /> </TableRow> </TableLayout>
Paso 2. Ve al archivo ActividadPrincipal.java y cambia el parámetro de setContentView()
con la referencia R.layout.ejemplo_table_layout
.
Paso 3. Ejecuta el proyecto para visualizar la siguiente impresión.
En el atributo android:stretchColumns del TableLayout usamos la columna 2 (indice 1) para rellenar el espacio horizontal restante ampliando el ancho de dicha columna.
Ejemplo De GridLayout
Un GridLayout es un ViewGroup
que alinea sus elementos hijos en una cuadrícula (grilla ó grid). Nace con el fin de evitar anidar linear layouts para crear diseños complejos.
Su funcionamiento se basa en un sistema de índices con inicio en cero. Es decir, la primera columna (o fila) tiene asignado el índice 0, la segunda el 1, la tercera el 2, etc.
Los atributos más importantes del GridLayout son:
columnCount
: Cantidad de columnas que tendrá la grilla.rowCount
: Cantidad de filas de la cuadrícula.useDefaultMargins
: Si asignas el valor detrue
para establecer márgenes predeterminadas entre los ítems.
En cuanto a sus parámetros, es posible especificar la cantidad de filas y columnas que ocupará una celda a través de los atributos android:layout_rowSpan
y android:layout_columnSpan
. Esta característica nos posibilita para crear diseños irregulares que un TableLayout
no permitiría.
El siguiente código muestra un TextView
que ocupa 2 columnas y 3 filas.
<TextView android:id="@+id/celda_1" android:layout_columnSpan="2" android:layout_rowSpan="3" android:text="Celda 1" />
En la ilustración mostrada al inicio, existe una cuadrícula de 8×4 con 5 views. Sus atributos span se encuentran escritos en de la forma axb.
Como ves, es posible expandir las celdas de forma horizontal y vertical. Incluso es posible proyectar views de forma cruzada.
Si observas bien, el elemento que se encuentra en la segunda fila con las especificaciones 1×2 se cruza en la columna 3. Esto se debe a que su ancho es de 3 unidades, per su atributo columnSpan
es igual a 2, lo que facilita al framework crear el cruce si existe espacio en blanco.
También puedes especificar a qué fila y columna pertenece cada view con los atributos android:layout_row
y android:layout_column
.
El siguiente TextView
se encuentra en la posición (0,0).
<TextView android:id="@+id/celda_1" android:layout_column="0" android:layout_row="0" android:text="Celda 1" />
En seguida, verás cómo construir un ejemplo…
Paso 1. Sigue la secuencia y crea un layout nuevo llamado ejemplo_grid_layout.xml. Esta vez diseñaremos el teclado de una calculadora simple.
<?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:alignmentMode="alignBounds" android:columnCount="4" android:rowCount="4"> <TextView android:id="@+id/numero_7" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_column="0" android:layout_row="0" android:text="7" /> <TextView android:id="@+id/numero_8" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="1" android:layout_row="0" android:text="8" /> <TextView android:id="@+id/numero_9" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_row="0" android:text="9" /> <TextView android:id="@+id/numero_4" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_height="wrap_content" android:layout_column="0" android:layout_row="1" android:text="4" /> <TextView android:id="@+id/numero_5" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="1" android:layout_row="1" android:text="5" /> <TextView android:id="@+id/numero_6" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_row="1" android:text="6" /> <TextView android:id="@+id/signo_por" style="@style/AppTheme.BotonCalculadora.Rojo" android:layout_column="3" android:layout_gravity="fill" android:layout_row="1" android:gravity="center" android:text="×" /> <TextView android:id="@+id/textView10" style="@style/AppTheme.BotonCalculadora.Rojo" android:layout_column="3" android:layout_gravity="fill_horizontal" android:layout_row="0" android:text="÷" /> <TextView android:id="@+id/numero_1" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_column="0" android:layout_row="2" android:text="1" /> <TextView android:id="@+id/numero_2" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="1" android:layout_row="2" android:text="2" /> <TextView android:id="@+id/numero_3" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_row="2" android:text="3" /> <TextView android:id="@+id/signo_menos" style="@style/AppTheme.BotonCalculadora.Rojo" android:layout_column="3" android:layout_gravity="fill_horizontal" android:layout_row="2" android:gravity="center" android:text="-" /> <TextView android:id="@+id/punto" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_column="0" android:layout_gravity="fill_horizontal" android:layout_row="3" android:gravity="center_horizontal" android:text="." /> <TextView android:id="@+id/cero" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_column="1" android:layout_row="3" android:text="0" /> <TextView android:id="@+id/signo_igual" style="@style/AppTheme.BotonCalculadora.Azul" android:layout_column="2" android:layout_gravity="fill_horizontal" android:layout_row="3" android:text="=" /> <TextView android:id="@+id/signo_mas" style="@style/AppTheme.BotonCalculadora.Rojo" android:layout_column="3" android:layout_gravity="fill_horizontal" android:layout_row="3" android:text="+" /> </GridLayout>
Paso 2. Modifica tu archivo de estilos res/values/styles.xml con las siguientes características para los botones de la calculadora. Serán dos tipos de botones, aquellos que representen los números con fondo azul y los que muestren los signos de operación aritmética de color rojo.
<style name="AppTheme.BotonCalculadora" parent="TextAppearance.AppCompat.Headline"> <item name="android:textColor">@android:color/white</item> <item name="android:gravity">center</item> <item name="android:padding">36dp</item> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> </style> <style name="AppTheme.BotonCalculadora.Azul" parent="AppTheme.BotonCalculadora"> <item name="android:background">#00537D</item> </style> <style name="AppTheme.BotonCalculadora.Rojo" parent="AppTheme.BotonCalculadora"> <item name="android:background">#EA4D39</item> </style>
Paso 3. Ahora reemplaza el recurso dentro de setContentView()
para inflar el layout con R.layout.ejemplo_grid_layout
.
Paso 4. Finalmente corre de nuevo el proyecto para ver los efectos.
Diseño De Layouts Con Android Studio
El editor visual de Android Studio facilita la creación de layouts con un sistema de drag and drop. Esto quiere decir, que podemos arrastrar elementos desde un panel hacia el lienzo del layout y ubicarlos instantáneamente.
Incluso podemos modificar los atributos y parámetros de forma visual sin tener que tocar el código XML.
En la vista de diseño tendremos una sección llamada Palette, la cual contiene todos los elementos gráficos posibles que podemos implementar dentro de un layout. Desde este lugar puedes seleccionar cualquier elemento y arrastrarlo al lienzo. Dentro de esta existen varias categorías, como Layouts, donde se encuentran los layouts que hemos visto hasta ahora.
El lienzo es simplemente la representación visual en tiempo real de la interfaz de la aplicación. Cuando arrastras un elemento de la paleta hacia el lienzo, este proyecta guías visuales para indicarte como será acomodado el view si lo sueltas en esa posición.
El panel de propiedades (Properties) muestra los atributos del view seleccionado. En el veremos una lista con pares clave-valor para escoger las opciones que deseamos sin ver el código XML.
La ilustración anterior muestra como al intentar arrastrar un TextView
de tipo «Large Text» hacia un FrameLayout, proyecta una ayuda visual para saber con qué valor del atributo gravity
será situado el componente. En este caso estamos la imagen muestra la tentativa de soltar el view en el centro ([center, center]).
Cada layout tiene su propia ayuda visual. Por ejemplo un relative layout proyecta flechas de alineación entre los views para saber en que borde se asignará un elemento.
Cambiar versión de Android— En las variaciones del editor visual, podemos cambiar la versión de Android con que se está mostrando el layout actual.
Esto con el fin de comprobar que los diseños funcionen de forma integral en versiones anteriores.
Para ello dirígete al icono del androide en la parte superior derecha y despliega la lista de versiones disponibles. Selecciona la que desees y analiza el cambio.
Si presionas la opción Preview Android Versions se desplegarán al mismo tiempo varios layouts con el diseño actual.
Visualizar layouts con múltiples idiomas— Si tienes traducciones para los strings relacionados a tus layouts, entonces puedes las respectivas variaciones con la opción del globo.
La ilustración anterior muestra que existe un recurso strings para el idioma inglés, por lo que al presionar la opción Preview All Locales veremos las variaciones en pantalla.
Variar el tema del layout— Otro cambio que puedes realizar, es la selección de un tema distinto para el renderizado del layout. Solo presiona el icono parecido a un eclipse.
Esto despliega un asistente con la lista de todos los estilos que tiene el sistema. Elige el que desees probar y confirma.
Rotar pantalla en Android Studio— Para cambiar de portrait a landscape o viceversa, utiliza el icono del dispositivo móvil con una flecha de rotación.
Visualizar el layout con un dispositivo diferente— Es posible emplear diferentes dispositivos para comprobar el funcionamiento del layout en densidades alternas.
En mi caso he usado el Nexus 5 para representar la interfaz, pero si presionas el icono cuya imagen tiene un dispositivo tras otro podrás acceder a más modelos.
Por otro lado, si eliges la opción Preview All Screen Sizes, Android Studio proyectará el layout en todos los dispositivos disponibles.
Crear variación landscape de un layout— En ocasiones los layout que creamos suelen desajustarse al momento de rotar la pantalla a landscape. Esto afecta la experiencia de usuario, ya que desaprovecha el espacio de acción y es posible que los views pierdan congruencia.
Un pequeño ejemplo de esta situación podemos verlo al rotar ejemplo_relative_layout.xml a landscape.
Debido a que el espacio horizontal casi es duplicado, el EditText
para los nombres se ve forzado. Una de las ideas para mejorar el diseño, podría ser mover el edit Text de apellidos a la derecha para compensar.
Solucionaremos esto creando un layout especial para orientación horizontal, donde haremos el cambio. Ve a la primera opción donde se ve un icono de un archivo junto al logo de android. Esto desplegará una lista de varias opciones, pero la que nos interesa es Create Landscape Variation.
Luego de haber seleccionado la opción, se creará automáticamente un layout con las mismas características de la variación portrait. Modifica su contenido con el siguiente diseño:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_horizontal_margin"> <EditText android:id="@+id/input_nombre" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_marginRight="48dp" android:ems="10" android:hint="Nombres" android:inputType="textPersonName" /> <EditText android:id="@+id/input_apellido" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/input_nombre" android:ems="10" android:hint="Apellidos" android:inputType="textPersonName" /> <TextView android:id="@+id/texto_estado_civil" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/input_apellido" android:paddingBottom="8dp" android:paddingTop="16dp" android:text="Estado civil" android:textAppearance="?android:attr/textAppearanceMedium" /> <Spinner android:id="@+id/spinner_cargo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/texto_estado_civil" android:layout_toLeftOf="@+id/spinner_estado_civil" android:entries="@array/lista_cargo" /> <TextView android:id="@+id/texto_cargo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/input_apellido" android:layout_below="@+id/input_apellido" android:paddingBottom="8dp" android:paddingTop="16dp" android:text="Cargo" android:textAppearance="?android:attr/textAppearanceMedium" /> <Spinner android:id="@+id/spinner_estado_civil" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/texto_cargo" android:layout_alignParentRight="true" android:layout_alignStart="@+id/texto_cargo" android:layout_below="@+id/texto_cargo" android:entries="@array/lista_estado_civil" /> </RelativeLayout>
Este producirá el siguiente resultado:
Si te fijas en el contenido de la carpeta res, verás que hay un nuevo directorio llamado layout-land. Como sabes, el calificador «land» indica que cuando el dispositivo rote a landscape, la aplicación buscará este diseño para implementarlo.
Conclusión
Los layouts son elementos que se utilizan en el diario vivir de un Desarrollador Android, sin embargo es necesario tener en claro cuál es la mejor opción ante un diseño particular.
En este artículo hemos visto 5 layouts populares para crear la UI. Su uso depende de la experiencia de usuario que deseas proporcionar junto al nivel de rendimiento de tu app.
Afortunadamente Android Studio nos provee un editor visual para crear diseños en tiempo real, observando los cambios de la interfaz para ajustar cambios.
Como tema adicional puedes investigar sobre layouts más complejos que se basan en adaptadores, como el ListView y el GridView. Ambos permiten crear conjuntos de elementos con carácteristicas similares.
La siguiente lista contiene los créditos a las imágenes usadas para la aplicación Android:
Únete Al Discord De Develou
Si tienes problemas con el código de este tutorial, preguntas, recomendaciones o solo deseas discutir sobre desarrollo Android conmigo y otros desarrolladores, únete a la comunidad de Discord de Develou y siéntete libre de participar como gustes. ¡Te espero!