Conceptos básicos de interfaces gráficas con AndroidEn esta sección vamos a introducirnos en el desarrollo de interfaces gráficas para
Android. Haremos un sencillo ejemplo paso a paso en donde la idea es que comprenda la filosofía con la que se trabaja al usar widgets y actividades. El resultado será una aplicación sencilla que pide una cadena de texto al usuario y la invierte. Es importante que ya tenga configurado el SDK y el Eclipse como se explica en el post anterior; aprenderemos a usar labels, cajas de texto, botones y eventos.
Puesto que es el primer post de este tipo, voy a explicar detalladamente cada paso. En las siguientes iré un poco más rápido. Así que, si ya tiene experiencia con Android tal vez se aburra un poco...
0. Crear un nuevo proyectoAbrimos Eclipse y creamos un nuevo proyecto para Android:
Configuramos el proyecto de tal manera que quede así:
En este caso estoy usando la versión 1.6 de Android, pero puede escoger la versión que concuerde con el dispositivo sobre el que desea probar la aplicación. Esto se explica con más detalle en el post anterior. Fíjese que no hemos creado ninguna actividad inicialmente (el checkbox
Create Activity no está seleccionado); la idea es ver cómo se deben crear las actividades, los layouts con la interfaz gráfica, las clases que referencian a las actividades y la configuración del
AndroidManifest.xml.
1. Crear y configurar una Actividad inicialCreamos una clase dentro del paquete
net.casidiablo.ejemplo:
Y en el asistente de creación de clases de Eclipse le damos como nombre
EjemploInvertir. Clic en Finish y editamos la clase para que luzca así:
package net.casidiablo.ejemplo;
import android.app.Activity;
import android.os.Bundle;
public class EjemploInvertir extends Activity{
@Override
public void onCreate(Bundle b){
super.onCreate(b);
setContentView(R.layout.main);
}
}
Lo que hemos hecho es extender la clase
Activity y redefinir el método
onCreate. Además, ejecutamos el método
setContentView indicándole que usaremos el layout
main.xml.
Puesto que deseamos que esta actividad sea mostrada al momento de ejecutar la aplicación, debemos editar el archivo
AndroidManifest.xml, que se encuentra en la raíz del proyecto. Al hacer doble clic sobre este, vemos que es posible editarlo usando una interfaz gráfica. Para añadir la actividad que acabamos de crear, hacemos clic en la pestaña inferior
Application, y en la sección
Application Nodes hacemos clic en
Add… Allí seleccionamos
Activity y hacemos clic en OK.
Ahora debemos configurar la actividad. En la parte derecha ha aparecido un formulario llamado
Attributes for Activity, en donde podremos hacerlo. Lo más importante es el nombre de la actividad, el cual debe ser el nombre de la clase que acabamos de crear. Es posible usar el botón
Browse… para buscar las actividades actualmente disponibles…
Una vez hayamos seleccionado o escrito el nombre de la clase, debemos añadirle un
Intent; pero… ¿qué es un
Intent ? Los componentes de una aplicación en Android se comunican a través de mensajes llamados
Intents (objetos de la clase
android.content.Intent). Se trata de una estructura de datos pasiva que contiene una descripción abstracta de una operación que será realizada, y se usa comúnmente para iniciar actividades. Sí ya se, es algo confuso al principio, pero de momento no es demasiado importante (más información
aquí). Para añadir el intent, seleccionamos la actividad que acabamos de crear y hacemos clic en el botón
Add… Seleccionamos
Intent Filter, hacemos clic en
OK. Y ahora, dentro del Intent crearemos dos componentes un
Action y un
Category.
Un
Action es un String que contiene el nombre de la acción a ser realizada. En este caso, el
Action será
android.intent.action.MAIN, el cual es usado para ejecutar la primera actividad de una aplicación. Entonces, seleccionamos el
Intent Filter que acabamos de crear, y hacemos clic en
Add… escogemos
Action, clic en
OK y escogemos el nombre del
Action:
Category es un
String que contiene información adicional acerca del tipo de componente que debería manipular el
Intent. En este caso el Category que añadiremos será
CATEGORY_LAUNCHER el cual indica que la actividad puede ser la principal (la que se ejecuta al iniciar la aplicación). Luego de añadir el
Category veremos que queda así:
Hacemos clic en el icono de guardar en la barra de herramientas y listo. También es posible editar el archivo
AndroidManifest.xml a mano, lo cual pienso que es mucho más rápido. Pero no esta de más saber cómo hacerlo con la interfaz gráfica. Si abrimos el archivo con el editor de XML veremos:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.casidiablo.ejemplo" android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name="EjemploInvertir">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"></category>
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>
Ahora que hemos configurado el
AndroidManifest.xml podemos hacer una prueba de ejecución del programa… si todo va bien veremos algo como esto:
2. Crear la interfaz gráficaEn este paso, crearemos una nueva interfaz gráfica que contendrá un label, una caja de texto y un botón. Aprenderemos a posicionar/agrupar los elementos en la pantalla, y darles un tamaño adecuado. Vamos a crear un nuevo layout dentro del directorio
res/layout/ (aunque podríamos haber usado el
main.xml generado por asistente de Eclipse, pero prefiero que aprenda este proceso de una vez). Así que, hacemos clic en el botón de creación de nuevos archivos XML de Android:
Seleccionamos la opción layout y le damos un nombre al archivo. Por ejemplo,
interfaz_grafica.xml:
¡Hacemos clic en
Finish y listo! Al hacer doble clic sobre el archivo que acabamos de crear vemos que es posible editarlo usando una interfaz gráfica, pero en este caso usaremos el editor de XML, ya que es mucho más rápido hacerlo así. Hacemos clic en la pestaña inferior que tiene el nombre del archivo (
interfaz_grafica.xml) y veremos algo como esto:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</LinearLayout>
Por defecto se crea un objeto
LinearLayout que contiene contiene tres parámetros: un
XML Name Space (en este caso
http://schemas.android.com/apk/res/android ), el tamaño que ocupará a lo ancho y el que ocupará a lo largo. Para estos dos ultimos parámetros se está usando
wrap_content indicando que se debe usar el menor espacio posible. Los objetos
LinearLayout funcionan de manera similar a los
JPanel de Java, pudiendo “contener” widgets de Android (labels, botones, menus u otros
LinearLayout, etc.).
Lo siguiente será crear la interfaz gráfica para nuestro programa de ejemplo, pero antes vamos a aprender un poco sobre el directorio
res/values. Por defecto veremos que hay un archivo llamado
strings.xml que contiene pares
nomber<=>valor. Este archivo es usado para almacenar todas las variables “estáticas” de la aplicación. Si bien su uso no es estrictamente obligatorio, si es recomendado y es bueno saber usarlo. Para nuestro ejemplo entonces, tenemos dos cadenas de texto que podrían ser estáticas: el texto que aparecerá en el label y el texto que aparecerá en el botón. Para la primera vamos a asignar el texto directamente en el XML de la interfaz gráfica, mientras que para el botón lo haremos usando el archivo
strings.xml; lo hago de las dos maneras con el fin de que quede clara la diferencia entre ambos métodos.
Abrimos el archivo
strings.xml, que se encuentra en el directorio
res/values, para añadir una nueva cadena de texto que será usada por el botón de la aplicación. Solo debemos añadir algo como esto:
<string name=”texto_boton”>Invertir!</string>, de tal manera que quede así:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World!</string>
<string name="app_name">Ejemplo</string>
<string name="texto_boton">Invertir!</string>
</resources>
Ahora sí, vamos a modificar el archivo
interfaz_grafica.xml de tal manera que quede así:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:text="Palabra: " android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText android:id="@+id/cajaTexto" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<Button android="@+id/btnInvertir" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/texto_boton"/>
</LinearLayout>
Veamos qué hemos hecho arriba:
- En la línea 3 podemos ver que cambiamos el ancho y alto del LinearLayout principal de tal manera que utilice toda la pantalla (usando fill_parent).
- Puesto que el LinearLayout contendrá otros objetos, debemos indicarle el sentido en el que los irá poniendo. En este caso se deben poner verticalmente (android:orientation="vertical").
- En las líneas 5 y 6 creamos un nuevo LinearLayout que contendrá el label y la caja de texto. Puesto que queremos que estos dos objetos aparezcan en una sola línea, ponemos el parámetro android:orientation="horizontal". Además, le indicamos que ocupe toda la pantalla a lo ancho, pero que la altura sea la más pequeña posible.
- En las líneas 7 y 8 creamos un nuevo TextView (un label) con el texto "Palabra: "; esto lo indicamos con la propiedad android:text. Además queremos que ocupe el menor espacio posible tanto en alto como en ancho (wrap_content para layout_width y layout_height).
- En las líneas 9 y 10 creamos un EditText (una caja de texto), que es donde el usuario pondrá la palabra que desea invertir. Intentará ocupar el mayor ancho posible en la pantalla. Además, puesto que este es un objeto del cual necesitaremos datos, debemos asignarle un ID para que podamos acceder a él desde el programa en Java que crearemos en breve.
- En la línea 11 cerramos el LinearLayout que contiene el label y la caja de texto.
- En las líneas 12 y 13 creamos un objeto Button. Este objeto también tiene un ID puesto que debemos obtener una referencia del mismo desde el programa en Java. Además, a la propiedad android:text se está asignando @string/texto_boton que es la referencia a la variable que creamos en el strings.xml
Ahora que hemos creado la interfaz gráfica, vamos a ejecutar la aplicación para ver si ha quedado bien. Pero antes, debemos indicarle a nuestra Actividad que el layout que debe ejecutar es
interfaz_grafica.xml. Esto lo hacemos modificando la clase
EjemploInvertir.java para que quede así:
package net.casidiablo.ejemplo;
import android.app.Activity;
import android.os.Bundle;
public class EjemploInvertir extends Activity{
@Override
public void onCreate(Bundle b){
super.onCreate(b);
setContentView(R.layout.interfaz_grafica);
}
}
Si todo va bien, al ejecutar la aplicación veremos algo como esto:
3. Programación de objetos de la interfaz gráficaAhora que hemos construido la interfaz gráfica, debemos programar la parte de “invertir la cadena de texto”. Para ello necesitamos extraer el texto que se ponga en la caja de texto y manejar los eventos que genera el botón; en cualquier caso, necesitamos referencias a dichos objetos. Así que, de momento, vamos a hacer que nuestra clase
EjemploInvertir.java luzca así:
package net.casidiablo.ejemplo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
public class EjemploInvertir extends Activity{
//declarar objetos
private EditText texto;
@Override
public void onCreate(Bundle b){
super.onCreate(b);
setContentView(R.layout.interfaz_grafica);
//iniciar los objetos
texto = (EditText) findViewById(R.id.cajaTexto);
boton
= (Button) findViewById
(R.
id.
btnInvertir); }
}
Veamos qué ha pasado allá arriba:
- En las líneas 4 y 5 importamos las clases Button y EditText del paquete android.widget.
- En las líneas 9 y 10 declaramos objetos de tipo EditText y Button, los cuales los usaremos para manipular los que hemos creado en la interfaz gráfica.
- En la líneas 17 iniciamos el objeto EditText usando el método findViewById, a la cual le enviamos como parámetro el ID de la caja de texto (¿recuerdas? pusimos esto dentro del XML: android:id="@+id/cajaTexto").
- De igual manera creamos el objeto botón usando el ID btnInvertir que definimos en el XML.
Hasta el momento solo hemos creado los objetos, pero no estamos haciendo nada con ellos. Para esto, vamos a asignar un listener al botón, que ejecutará ciertas acciones al momento de presionarlo. Esto lo hacemos con el método
setOnClickListener el cual recibe como parámetro un objeto de tipo
android.view.View.OnClickListener. Veamos cómo debe quedar la clase y luego explico cada componente nuevo:
package net.casidiablo.ejemplo;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class EjemploInvertir extends Activity{
//declarar objetos
private EditText cajaDeTexto;
@Override
public void onCreate(Bundle b){
super.onCreate(b);
setContentView(R.layout.interfaz_grafica);
//iniciar los objetos
cajaDeTexto = (EditText) findViewById(R.id.cajaTexto);
boton
= (Button) findViewById
(R.
id.
btnInvertir); boton.setOnClickListener(new OnClickListener() {
@Override
public void onClick
(View v
) { invertir();
}
});
}
//metodo para invertir el texto
private void invertir(){
//obtener el string de la caja de texto
String txt
= cajaDeTexto.
getText().
toString(); //verificar que haya texto por invertir
if(!txt.equals("")){
//invertir texto
for (int i = txt.length()-1; i>=0; i--)
resultado += txt.charAt (i);
//asignamos el string invertido a la caja de texto
cajaDeTexto.setText(resultado);
}
else Toast.makeText(this, "No hay nada que invertir", Toast.LENGTH_LONG).show();
}
}
Veamos que fue todo eso…
- En la línea 5 se importan la interfaz OnClickListener. Dicha interfaz es usada en la línea 20 al crear un objeto que se enviará como parámetro al método setOnClickListener. Dentro, es necesario implementar el método onClick en donde pondremos las instrucciones que serán ejecutadas al momento de hacer clic en el botón (en este caso una llamada a la función invertir(), líneas 28 a 41).
- El método invertir inicia una variable String con los datos que contenga la caja de texto, usando el método getText de la clase EditText.
- En las líneas 35 y 36 se invierte la cadena, que posteriormente se pone de nuevo en la caja de texto usando el método setText (línea 38).
- En la línea 40 mostramos un mensaje usando la clase Toast. Este mensaje aparece cuando no hay datos en la caja de texto. Lo he colocado puesto que es bastante sencillo de implementar. Basta con usar el método estático makeText pasándole como parámetros el contexto en el que se mostrará (se usa this, puesto que se mostrará en la Actividad actual), el texto a mostrar y cuanto tiempo durará el mensaje.
Al ejecutar la aplicación, escribir “
Estoy invertido” en la caja de texto y presionar el botón, veremos algo así:
Si no ponemos texto y presionamos el botón
Invertir, veremos:
La aplicación está lista para ser probada en un dispositivo real. En mi caso la instalé en una HTC Tattoo y se ve así:
4. Descargar códigoEste es el código fuente usado para este tutorial, espero le haya gustado. Cualquier duda o sugerencia no dude en comentarla.