Construyendo una sencilla interfaz de usuario

La interfaz gráfica de usuario de una aplicación Android se construye utilizando una jerarquía de objetos View (vista) y ViewGroup (grupo de vistas). Normalmente los objetos View son controles de interfaz de usuario como botones o campos de texto y los objetos ViewGroup son contenedores de vistas invisibles que definen cómo se distribuyen las vistas hijas, como una rejilla o una lista vertical.

Android proporciona un vocabulario XML que se corresponde con las subclases de View y ViewGroup de forma que puedes definir tu interfaz de usuario en XML usando una jerarquía de elementos de interfaz de usuario.

Figura 1. Ilustración de cómo los objetos ViewGroup forman ramas en la interfaz de usuario y contienen otros objetos View.

En esta lección, crearás una interfaz de usuario en XML la cuál incluirá un campo de texto y un botón. En la siguiente lección, aprenderás a responder a las pulsaciones en el botón enviando el contenido del campo de texto a otra actividad.

Crear un diseño lineal


Abre el archivo activity_main.xml situado en el directorio res/layout/.

Nota: En Eclipse, cuando abres un archivo de interfaz de usuario, lo primero que se muestra es el editor gráfico de interfaces de usuario. Este es un editor que te permite construir diseños usando herramientas WYSIWYG. Para esta lección, trabajarás directamente con XML, así que haz clic en la pestaña activity_main.xml en la parte inferior de la pantalla para abrir el editor XML.

La plantilla BlankActivity que seleccionaste cuando creaste este proyecto incluye un archivo activity_main.xml con un RelativeLayout como vista raíz y un TextView como vista hija.

Primero, borra el elemento <TextView> y cambia el elemento <RelativeLayout> por <LinearLayout>. Una vez hecho esto añade el atributo android:orientation y dale un valor de "horizontal". El resultado tendrá este aspecto:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="horizontal" >
</LinearLayout>

LinearLayout es un grupo de vistas (una subclase de ViewGroup) que distribuye las vistas hijas con una orientación horizontal o vertical, según lo especificado por el atributo android:orientation. Cada hijo de un LinearLayout se muestra en pantalla en el mismo orden en que aparece en el XML.

Los otros dos atributos, android:layout_width y android:layout_height, son requeridos por todas las vistas para poder especificar su tamaño.

Como el LinearLayout es la vista raíz en la interfaz, debería llenar todo el espacio disponible para la aplicación estableciendo su ancho y alto a "match_parent" (coincidir con el padre). Este valor declara que la vista debería expandir su ancho y alto para coincidir en ancho y alto con la vista padre.

Para más información sobre propiedades de interfaz de usuario, ver la guía de Interfaces de usuario.

Añadir un campo de texto


Para crear un campo de texto editable por el usuario, añade un elemento <EditText> dentro del <LinearLayout>.

Como con todo objeto de tipo View, debes definir ciertos atributos XML para especificar las propiedades del objeto EditText. Así es como deberías declararlo dentro del elemento <LinearLayout>:

    <EditText android:id="@+id/edit_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />

Acerca de estos atributos:

android:id
Proporciona un identificador único para la vista que puedes utilizar para referenciar el objeto en el código de tu aplicación, por ejemplo, para leer y manipular el objeto (veremos esto en la próxima lección).

Es necesario usar el símbolo arroba (@) cuando referencias un objeto recurso desde XML. Viene seguido por el tipo de recurso (id en este caso), una barra diagonal, y el nombre del recurso (edit_message).

El símbolo más (+) antes del tipo de recurso sólo se utiliza cuando estás definiendo un ID de recurso por primera vez. Cuando compiles la aplicación, las herramientas del SDK utilizarán el nombre del ID para crear un nuevo ID de recurso en el archivo gen/R.java de tu proyecto haciendo referencia al elemento EditText. Una vez se haya declarado el ID de recurso de esta forma, otras referencias a este ID no necesitarán del signo más. Usar el signo más sólo es necesario cuando especificamos un nuevo ID de recurso y no es necesario para recursos concretos como cadenas de texto y diseños. Consulta la caja lateral para más información acerca de los objetos recurso.

android:layout_width y android:layout_height
En lugar de utilizar tamaños específicos para el ancho y el alto, el valor "wrap_content" (ajustar al contenido) especifica que la vista debería tener el tamaño justo necesario para ajustarse al contenido de la vista. Si en su lugar utilizáramos "match_parent", entonces el elemento EditText llenaría toda la pantalla, porque se le haría coincidir en tamaño con el LinearLayout padre. Para más información, lee la guía de Interfaces de usuario.
android:hint
Esta es la cadena de texto a mostrar por defecto cuando el campo de texto esté vacío. En lugar de utilizar una cadena prefijada, el valor "@string/edit_message" hace referencia a un recurso de tipo cadena definido en un archivo aparte. Como hace referencia a un recurso concreto (no sólo un identificador), no necesita del signo más. Sin embargo, dado que todavía no hemos definido el recurso cadena, se mostrará un error de compilación. Arreglaremos esto en la próxima sección, cuando definamos la cadena.

Nota: Este recurso cadena tiene el mismo nombre que el ID del elemento: edit_message. Sin embargo, las referencias a recursos tienen un ámbito definido por el tipo de recurso (como id o string), por lo que no hay conflictos de nombre aunque usen el mismo nombre.

Añadir recursos cadena


Cuando necesites añadir un texto en la interfaz de usuario, siempre deberías especificar las cadenas como recursos. Los recursos cadena permiten gestionar todos los textos de la interfaz de usuario en un solo lugar, lo que hace más fácil encontrar y actualizar un texto. Externalizar las cadenas también te permite traducir tu aplicación a distintos idiomas proporcionando definiciones alternativas para cada recurso cadena.

Por defecto, tu proyecto Android incluye un archivo de recursos cadenas en res/values/strings.xml. Añade una nueva cadena llamada "edit_message" y dale como valor "Enter a message" o "Introduce un mensaje" (Puedes borrar la cadena "hello_world".)

Aprovechando que estás editando este archivo, añade también una cadena "Send" (Enviar) para el botón que añadiremos después, llamado "button_send".

El resultado para strings.xml tiene este aspecto:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">My First App</string>
    <string name="edit_message">Enter a message</string>
    <string name="button_send">Send</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">MainActivity</string>
</resources>

Para más información acerca del uso de recursos cadena para localizar tu aplicación para otros idiomas, consulta la clase Soportando distintos dispositivos.

Añadir un botón


A continuación añade un <Button> al diseño, inmediatamente después del elemento <EditText>:

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />

El alto y el ancho tienen como valor "wrap_content" para que el botón tenga justo el tamaño necesario para ajustarse al texto del botón. El botón no necesita el atributo android:id porque no haremos referencia a él en el código de la actividad.

Hacer que la caja de texto ocupe todo el ancho de la pantalla


En el diseño en que estamos trabajando tanto el elemento EditText como el elemento Button tienen justo el tamaño necesario para mostrar su contenido, como podemos ver en la figura 2.

Figura 2. Los controles EditText y Button tienen un valor de "wrap_content" para su ancho.

Esto nos sirve para el botón, pero no es una gran idea para el caso del campo de texto, porque el usuario puede querer introducir un texto mayor. Por tanto, estaría bien que el campo de texto ocupara el resto del ancho disponible. Puedes lograr esto dentro de un LinearLayout utilizando la propiedad weight (peso), que podemos especificar mediante el atributo android:layout_weight.

El peso es un número que especifica la cantidad del espacio restante que debería consumir cada vista, de forma relativa a la cantidad consumida por las vistas hermanas. Esto funciona un poco como los ingredientes de un cóctel: "2 partes de vodka, 1 parte de licor de café" significa que dos terceras partes de la bebida es vodka. Por ejemplo, si le das a una vista un peso de 2 y a otra un peso de 1, la suma es 3, así que la primera vista ocuparía 2/3 del espacio restante y la segunda vista ocuparía el resto. Si añades una tercera vista y le das un peso de 1, entonces la primera vista (con un peso de 2) ocuparía la mitad del espacio restante, y las otras dos vistas ocuparían cada una 1/4.

Por defecto el valor del peso de todas las vistas es 0, por lo que si especificas cualquier valor de peso mayor que 0 para una sola vista, entonces esa vista ocupará todo el espacio restante una vez se le haya dado a cada vista el espacio que necesitaba. Así que, para hacer que el elemento EditText ocupe todo el espacio restante de la interfaz, dale un valor de 1 al peso y deja el botón sin peso.

    <EditText
        android:layout_weight="1"
        ... />

Para mejorar la eficiencia de la interfaz de usuario cuando especifiques el peso, deberías cambiar el ancho del EditText a cero (0dp). Dar un valor de cero al ancho mejora el rendimiento del diseño porque usar el valor "wrap_content" requiere que el sistema calcule un ancho que al final va a terminar siendo irrelevante dado que el valor del peso requiere de otro cálculo para el ancho para hacer que ocupe todo el espacio restante.

    <EditText
        android:layout_weight="1"
        android:layout_width="0dp"
        ... />

La figura 3 muestra el resultado de asignar todo el peso al elemento EditText.

Figura 3. Se le da todo el peso de la interfaz al control EditText, lo que hace que ocupe todo el espacio restante en el LinearLayout.

Este es el aspecto que debería tener tu archivo de interfaz de usuario una vez terminado:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="horizontal">
    <EditText android:id="@+id/edit_message"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />
</LinearLayout>

La clase Activity que las herramientas del SDK generaron cuando creaste el proyecto utiliza este archivo de interfaz de usuario por defecto, por lo que ya puedes ejecutar la aplicación para ver el resultado:

  • En Eclipse, haz clic en el botón Run de la barra de herramientas.
  • O en la línea de comandos, abre el directorio raíz de tu proyecto Android y ejecuta:
    ant debug
    adb install bin/MyFirstApp-debug.apk
    

Continúa con la siguiente lección para aprender cómo puedes responder a pulsaciones en el botón, leer el contenido del campo de texto, iniciar otra actividad, y mucho más.