Diseño de la interfaz de usuario: Vistas y Layouts
Introducción
El diseño de la interfaz de usuario cobra cada día más importancia en el desarrollo de una aplicación. La calidad de la interfaz de usuario puede ser uno de los factores que conduzca al éxito o al fracaso de todo el proyecto.
Si has realizado alguna aplicación utilizando otras plataformas, advertirás que el diseño de la interfaz de usuario en Android sigue una filosofía muy diferente. En Android la interfaz de usuario no se diseña en código, sino utilizando un lenguaje de marcado en XML similar al HTML.
A lo largo de este capítulo mostraremos una serie de ejemplos que te permitirán entender el diseño de la interfaz de usuario en Android. Aunque no será la forma habitual de trabajar, comenzaremos creando la interfaz de usuario mediante código. De esta forma comprobaremos que cada uno de los elementos de la interfaz de usuario (las vistas) realmente son objetos Java. Continuaremos mostrando cómo se define la interfaz de usuario utilizando código XML. Pasaremos luego a ver las herramientas de diseño integradas en Eclipse. Se describirá el uso de layouts, que nos permitirá una correcta organización de las vistas, y el uso de recursos alternativos nos permitirá adaptar nuestra interfaz a diferentes circunstancias y tipos de dispositivos.
En este capítulo también comenzaremos creando la aplicación de ejemplo desarrollada a lo largo del curso, MisLugares o Asteroides, según el curso que estes siguiendo. Crearemos la actividad principal, donde simplemente mostraremos cuatro botones, con los que se podrán arrancar diferentes actividades. A continuación aprenderemos a crear estilos y temas y los aplicaremos a estas actividades. Para terminar el capítulo propondremos varias prácticas para aprender a utilizar diferentes tipos de vistas ylayouts.
Objetivos
-
Entender cómo se realiza el diseño del interfaz de usuario en una aplicación Android.
-
Aprender a trabajar con vistas y mostrar sus atributos más importantes.
-
Enumerar los tipos de Layouts que nos permitirán organizar las vistas.
-
Mostrar cómo se utilizan los recursos alternativos.
-
Aprenderemos a crear estilos y temas para personalizar nuestras aplicaciones.
-
Mostrar cómo interactuar con las vistas desde el código Java
-
Describir el uso de layouts basados en pestañas (tabs).
Creación de una interfaz de usuario por código
Veamos un primer ejemplo de cómo crear una interfaz de usuario utilizando exclusivamente código Java. Aunque esta no es la forma recomendable de trabajar con Android, resulta interesante para resaltar algunos conceptos.
Creación del interfaz de usuario por código
1. Abre el proyecto creado en el capítulo anterior y visualiza MainActivity.java.
2. Comenta la última sentencia del método onCreate() añade las tres que se muestran a continuación en negrita:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
TextView texto = new TextView(this);
texto.setText("Hello, Android");
setContentView(texto);
}
Nota sobre Java: Para poder utilizar el objeto TextView has de importar un nuevo paquete. Para ello añade al principio “import android.widget.TextView;”. Otra alternativa es pulsar Alt-Intro en Android Studio o Ctrl-Shift-O enEclipse, para que se añadan automáticamente los paquetes que faltan.
La interfaz de usuario de Android está basada en una jerarquía de clases descendientes de la clase View(vista). Una vista es un objeto que se puede dibujar y se utiliza como un elemento en el diseño de la interfaz de usuario (un botón, una imagen, una etiqueta de texto como en el utilizado en el ejemplo,…). Cada uno de estos elementos se define como una subclase de la clase View; la subclase para representar un texto es TextView.
El ejemplo comienza creando un objeto de la clase TextView. El constructor de la clase acepta como parámetro una instancia de la clase Context (contexto). Un contexto es un manejador del sistema que proporciona servicios como la resolución de recursos, obtención de acceso a bases de datos o preferencias. La claseActivity es una subclase de Context, y como la clase MainActivity es una subclase de Activity, también es tipo Context. Por ello, puedes pasar this (el objeto actual de la clase MainActivity) como contexto delTextView.
3. Después se define el contenido del texto que se visualizará en el TextView mediante setText(). Finalmente, mediante setContentView()se indica la vista utilizada por la actividad.
4. Ejecuta el proyecto para verificar que funciona.
Creación de una interfaz de usuario usando XML
En el ejemplo anterior hemos creado la interfaz de usuario directamente en el código. A veces puede ser muy complicado programar interfaces de usuario, ya que pequeños cambios en el diseño pueden corresponder a complicadas modificaciones en el código. Un principio importante en el diseño de software es que conviene separar todo lo posible el diseño, los datos y la lógica de la aplicación.
Android proporciona una alternativa para el diseño de interfaces de usuario: los ficheros de diseño basados en XML. Veamos uno de estos ficheros. Para ello accede al fichero res/layout/activity_main.xml de nuestro proyecto. Se muestra a continuación. Este layout o fichero de diseño proporciona un resultado similar al del ejemplo de diseño por código anterior:
<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"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
NOTA: Cuando haces doble clic en el explorador del proyecto sobre activity_main.xml, probablemente lo abra en modo gráfico. Para verlo en modo texto selecciona la pestaña Text enAndroid Studio o activity_main.xml en Eclipse.
Resulta sencillo interpretar su significado. Se introduce un elemento de tipo RelativeLayout, como se estudiará más adelante su función es contener otros elementos de tipo View. Este RelativeLayout tiene cinco atributos. Los dos primeros,xmlns:android,y xmlns:tools son declaraciones de espacios de nombres de XML que utilizaremos en este fichero (este tipo de parámetro solo es necesario especificarlo en el primer elemento). Los dos siguientes permiten definir el ancho y alto de la vista. En el ejemplo se ocupará todo el espacio disponible. El último atributo indica la actividad asociada a este Layout.
Dentro del RelativeLayout solo tenemos un elemento de tipo TextView. Este dispone de tres atributos. Los dos primeros definen el ancho y alto (se ajustará al texto contenido). El último indica el texto a mostrar. No se ha indicado un texto directamente sino una referencia, "@string/hello_world". Esta referencia ha de estar definida en el fichero res/values/strings.xml. Si abres este fichero, tienes el siguiente contenido:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Hola Mundo</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
</resources>
Esta es la práctica recomendada en Android para la inserción de textos en tu aplicación, dado que facilita su localización a la hora de realizar la traducción a otros idiomas. Es decir, utilizaremos los ficheros layout para introducir el diseño de los interfaces y el fichero strings para introducir los textos utilizados en los distintos idiomas.
Creación del Interfaz de usuario con XML
1. Para utilizar el diseño en XML regresa al fichero MainActivity.java y deshaz los cambios que hicimos antes (elimina las tres últimas líneas y quita el comentario).
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
2. Ejecuta la aplicación y verifica el resultado. Ha de ser muy similar al anterior.
3. Modifica elvalor de hello_world en el fichero res/values/strings.xml.
4. Vuelve a ejecutar la aplicación y visualiza el resultado.
Analicemos ahora la línea en la que acabas de quitar el comentario:
setContentView(R.layout.activity_main) ;
Aquí, R.layout.main corresponde a un objeto View que será creado en tiempo de ejecución a partir del recurso activity_main.xml. Trabajar de esta forma, en comparación con el diseño basado en código, no quita velocidad y requiere menos memoria. Este identificador es creado automáticamente en la clase R del proyecto a partir de los elementos de la carpeta res. La definición de la clase R puede ser similar a:
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int ic_launcher=0x7f020000;
}
public static final class id {
public static final int menu_settings=0x7f070000;
}
public static final class layout {
public static final int activity_main=0x7f030000;
}
public static final class menu {
public static final int activity_main=0x7f060000;
}
public static final class string {
public static final int app_name=0x7f040000;
public static final int hello_world=0x7f040001;
...
NOTA: Este fichero se genera automáticamente. Nunca debes editarlo.
Has de tener claro que los identificadores de la clase R son meros números que informan al gestor de recursos, que datos ha de cargar. Por lo tanto no se trata de verdaderos objetos, estos serán creados en tiempo de ejecución solo cuando sea necesario usarlos.
El fichero R.java.
1. En Eclipse abre el fichero que encontraras en el explorador de proyecto engen/com.example.holamundo/R.java de tu aplicación. En Android Studio, este fichero no es accesible desde el explorador de proyecto. No obstante, también puedes acceder a él si pulsas con el botón derecho sobre app y seleccionas Show in Explorer. Desde esta carpeta abre el fichero:
app\build\generated\source\r\debug\nombre\del\paquete\R.java
Donde nombre\del\paquete has de reemplazarlo por el que corresponda al paquete de tu aplicación.
2. Comparalo con el fichero mostrado previamente. ¿Qué diferencias encuentras? (RESPUESTA: en Eclipse cambianlos valores numéricos en hexadecimal en Android Studio el fichero contiene muchos más identificadores).
3. Abre el fichero MainActivity.java y reemplaza R.layout.activity_main por el valor numérico al que corresponde en R.java.
4. Ejecuta de nuevo el proyecto. ¿Funciona? ¿Crees que sería adecuado dejar este valor numérico?
5. Aunque haya funcionado, este valor puede cambiar en un futuro. Por lo tanto para evitar problemas futuros vuelve a reemplazarlo por R.layout.activity_main.