Layouts
Los layouts son contenedores de vistas (V iewGroup) predefinidos ofrecidos por Android. Cada layout
proporciona un estilo de representación en página distinto permitiendo a las vistas posicionarse las
unas respecto a las otras o respecto al contenedor padre.
Los principales layouts predefinidos
son FrameLayout, LinearLayout, RelativeLayout,TableLayout. Ofrecen respectivamente
una estructura de posicionamiento de las vistas en marco, lineal, relativa y en forma de tabla.
Tenga precaución de no confundir los archivos de layout, definidos en la carpeta / res/layout/, con
los contenedores de vistas: los archivos de layout son archivos que permiten componer la interfaz
visual de una actividad en modo declarativo, los contenedores de
vista f rameLayout yLinearLayout son objetos que estructuran la presentación en página.
Típicamente, un archivo de layout contiene, como primer elemento, un contenedor de vistas (ya sea
un FrameLayout, un Ta bleLayout o, con frecuencia, un LinearLayout o
un Re lativeLayout).
FrameLayout
Contenedor reducido a su mínima expresión. Todo lo que contiene se dibujará a partir de la esquina
superior izquierda. Los últimos elementos hijos agregados se dibujarán debajo de los más antiguos.
LinearLayout
Contenedor en el que los elementos hijos se disponen en función del valor del atributo de orientación:
Verticalmente, los unos debajo de los otros, un único elemento por línea.
Horizontalmente, los unos a continuación de los otros, a la derecha del anterior.
RelativeLayout
Contenedor en el que las posiciones de las vistas hijas están determinadas respecto a la vista padre o
respecto a otras vistas hijas. El uso del contenedor R elativeLayoutse estudia con detalle en el
capítulo Construir interfaces complejas, sección Representación en pantalla compleja.
TableLayout
Contenedor en el que los elementos hijos se disponen en forma de tabla. Las vistas hijas son
objetos TableRow que definen cada uno una línea de la tabla. Los elementos hijos de los
objetos TableRow son celdas de la tabla. Observe que dichas tablas no disponen, hablando con
propiedad, de columnas, como ocurre con HTML.
1. Creación en modo declarativo
El modo declarativo es el modo más sencillo para declarar la interfaz de usuario de una pantalla.
Veamos cómo crear un layout en un archivo XML.
La primera etapa consiste en crear un archivo con formato XML, en la carpeta res/layout del
proyecto.
Recuerde (véase el capítulo Primeros pasos - Estructura de un proyecto Android), el nombre de la
carpeta la youtpuede especializarse para filtrar el uso de los layouts según ciertas características.
En posible en particular proveer distintos layouts para una misma pantalla, a modo de interfaz, según
la categoría del tamaño de la pantalla física. Para ello, el calificador que debe usarse es el nombre de
la categoría correspondiente al tamaño de pantalla.
Los recursos que se encuentran en la carpeta res/layoutestán clasificados como recursos
para pantallas de tamaño normal (normal).
Ejemplo
res/layout-small/layout_principal.xml
res/layout-normal/layout_principal.xml
res/layout-xlarge/layout_principal.xml
También es posible crear layouts distintos según la orientación de la pantalla. El calificativo que debe
especificar es po rtpara el modo vertical y landpara el modo apaisado. Es posible combinar las
distintas categorías de calificadores para afinar al máximo el filtrado.
Ejemplo
res/layout-port/layout_principal.xml
res/layout-xlarge-land/layout_principal.xml
El archivo layout XML debe tener la sintaxis siguiente:
Sintaxis
<xml version="1.0" encoding="utf-8">
<Tipo_de_layout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="dimensión"
android:layout_height="dimensión"
... >
...
</Tipo_de_layout>
La primera línea describe la versión XML y la codificación del archivo.
La segunda línea especifica el tipo de layout deseado utilizando la etiqueta XML correspondiente. Se
especifican a continuación las propiedades de esta etiqueta y, por tanto, del layout.
El layout raíz de la pantalla debe especificar el atributo xmlns:android con el valor
asignado anteriormente para definir el espacio de nombres android que se utilizará para la
declaración de los atributos.
Los atributos android:layout_width y android:layout_height son obligatorios, y se
produce una excepción en caso contrario.
Los posibles valores de estos atributos son:
match_parent: la vista mide igual que la vista padre menos el valor del espaciado
(padding). Desde la versión 8 del SDK, este valor reemplaza al valor fill_parent.
wrap_content: la vista mide igual que las dimensiones de su contenido más el valor del
espaciado (padding). Es decir, el tamaño más pequeño posible pero suficiente como para
mostrar su contenido.
una dimensión: la vista se dimensiona de forma precisa según este valor. Una dimensión
descrita por un número, en coma flotante si fuera preciso, seguido de una unidad. Por
ejemplo: 42 dp.
Recuerde, para que una aplicación pueda adaptarse a cualquier tipo de pantalla, tamaño y
resolución, se recomienda encarecidamente utilizar únicamente dimensiones independientes de
la densidad. De este modo, para las dimensiones de un layout, se dará prioridad a los
valores match_parent, wrap_contenty a aquellas especificadas en dp.
Ejemplo
<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" >
</RelativeLayout>
En este ejemplo, la pantalla aplica un layout relativo cuyas dimensiones son las de la vista padre. Es
decir, en este caso la pantalla completa salvo por la barra de estado y la barra de título en la parte
superior.
Una buena práctica, que resulta esencial en un entorno de producción, es prefijar los nombres de los
archivos XML de layout con el término ’layout_’, puesto que en la carpeta layout puede haber, como
veremos en próximos capítulos, otros tipos de archivos. Como resulta imposible crear subcarpetas en
la carpeta /res/layout, es bastante difícil ubicarse si no se adquiere este hábito.
2. Creación en modo programático
El modo programático es el más flexible y el más potente de los dos modos. En contrapartida,
también es el más complejo.
Permite generar dinámicamente la interfaz de usuario tras la creación de la actividad. También, y
principalmente, permite modificar esta interfaz dinámicamente durante la ejecución de la aplicación,
por ejemplo, cuando un botón OK deshabilitado debe activarse si el usuario rellena todos los campos
de un formulario.
Creación del layout
Para crear un layout, es preciso instanciar un nuevo objeto de la clase del tipo de layout deseado.
Tomemos, por ejemplo, un layout relativo.
Sintaxis
public RelativeLayout (Context context)
Este constructor recibe como parámetro un contexto. De momento, quedémonos con la idea de que
un contexto sirve para reagrupar un conjunto de información asociada al entorno de la aplicación, y
que la clase Activityhereda indirectamente de la clase Context.
Una vez creado el objeto, hay que especificar sus dimensiones usando su
método setLayoutParams.
Sintaxis
public void setLayoutParams (ViewGroup.LayoutParams params)
Este método recibe como parámetro un objeto de tipo ViewGroup.LayoutParams. Es preciso
crear uno utilizando uno de sus constructores.
Sintaxis
public ViewGroup.LayoutParams (int width, int height)
Los parámetros wi dthy heightson números enteros. Como hemos visto anteriormente, puede
ser un valor a escoger entre match_parent, wrap_contento una dimensión.
Para terminar, es preciso definir este layout como vista raíz de la actividad para construir su interfaz
de usuario gracias al segundo método setContentViewque recibe esta vez como parámetro un
objeto de tipo View.
Sintaxis
public void setContentView (View view)
Ejemplo
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout layout = new RelativeLayout(this);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
layout.setLayoutParams(lp);
setContentView(layout);
}
En este ejemplo, el constructor Rela tiveLayout recibe como parámetro this dado que el
método onCreate ejecutado corresponde al de un objeto que hereda de la clase Activity,
heredando ella misma de la clase Context.