Documente Academic
Documente Profesional
Documente Cultură
S diferente, intgrate
Mca006
Manual Mca006
INDICE
Leccin 1 Ambiente de Programacin Android: Java Development Kit, Eclipse Juno, SDK de Android,
Pag. 3
Pluggin de Android para Eclipse
Pag. 6
Pag. 17
Pag. 18
Pag. 23
Pag. 31
Pag. 33 Leccin 7 Controles bsicos: Button, TogleButton, ImageButton, ImageView, TextView, EditText,
Objetos Tipo Spanned, Formatos en objetos de texto, CheckBox, RadioBotton
Pag. 42 Leccin 8 Controles de Seleccin: Adaptadores, Listas desplegables tipo Spinner, Listas fijas tipo
ListView, GridView
Pag. 46 Leccin 9 Controles personalizados: Extendiendo la funcin de un control existente, Combinando
varios controles para crear uno ms complejo, Diseando un control desde cero
Pag. 64
Pag. 69
Leccin 11 Fragments
Pag. 79
Pag. 80
Leccin 13 Mens: Mens y Sub Mens bsicos, Mens contextuales, Opciones Avanzadas
Pag. 90
Leccin 14 Widgets
Pag. 94
Pag. 102
Pag. 104
Leccin 17 Mapas : Comparacin v1 y v2, Introduccin v2, Objeto Google Map, Mtodos
Pag. 111
Manual Mca006
LECCION 1 Ambiente de Programacin Android: Java Development Kit, Eclipse Juno, SDK de Android,
Pluggin de Android para Eclipse
Ambiente de desarrollo en Android
A continuacin se describen los pasos bsicos para disponer en el equipo del ambiente y las herramientas
necesarias para comenzar a programar aplicaciones para la plataforma Android.
Paso 1. Descargar e instalar Java.
Se debe instalar alguna versin del JDK (Java Development Kit) de Java, la misma se encuentra disponible en el
sitio web de Oracle http://www.oracle.com/technetwork/java/javase/downloads/index.html.
Por ejemplo, se puede descargar la versin 7 update11, la cual dependde de la versin concreta del sistema de
operacin. Por ejemplo, para Windows 64 bits se puede descargar el ejecutable marcado como Windows x64
cuyo nombre de archivo es jdk-7u11-windows-x64.exe.
La instalacin no tiene ninguna dificultad ya que es un instalador estndar de Windows donde tan slo hay que
aceptar las opciones que ofrece por defecto.
Manual Mca006
funciona perfectamente con Eclipse 4.2.1). Con las ltimas versiones, Google proporciona un paquete que contiene
Eclipse, el SDK y varios de los componentes necesarios ya instalados (el paquete se llama ADT Bundle for
Windows), pero para descargar e instalar cada elemento por separado, se utiliza el enlace Use an existing IDE y
se descarga el ADT pulsando sobre el botn Download the SDK Tools for Windows. Una vez descargado, bastar
con ejecutar el instalador estndar de Windows.
Paso 4. Descargar el plugin Android para Eclipse.
Google pone a disposicin de los desarrolladores un plugin para Eclipse llamado Android Development Tools (ADT)
que facilita en gran medida el desarrollo de aplicaciones para la plataforma. Se puede descargar mediante las
opciones de actualizacin de Eclipse, accediendo al men Help / Install new software e indicando el siguiente
URL de descarga:
https://dl-ssl.google.com/android/eclipse/
Se seleccionan los dos paquetes disponibles Developer Tools y NDK Plugins y se pulsa el botn Next> para
comenzar con el asistente de instalacin.
Durante la instalacin Eclipse requerir la aceptacin de la licencia de los componentes de Google que se van a
instalar y es posible que aparezca algn mensaje de warning que simplemente se puede aceptar para continuar
con la instalacin. Finalmente el instalador solicitar la reinicializacin de Eclipse.
Paso 5. Configurar el plugin ADT.
Una vez instalado el plugin, se debe configurar indicando la ruta donde se ha instalado el SDK de Android. Para
ello, se ir a la ventana de configuracin de Eclipse (Window / Preferences), y en la seccin de Android se
indicara la ruta donde se ha instalado. Finalmente se pulsa OK para aceptar los cambios. Si aparece algn mensaje
de warning el mismo se acepta, ya que se son problemas que se solucionarn en el siguiente paso.
Manual Mca006
Manual Mca006
seccin Virtual Devices se pueden aadir tantos AVD como se necesiten (por ejemplo, configurados para distintas
versiones de Android o distintos tipos de dispositivo). Se recomienda configurar al menos dos AVD, uno para la
mnima versin de Android a soportar, y otro para la versin ms reciente disponible.
Para configurar el AVD tan slo de debe indicar un nombre descriptivo, la versin de la plataforma Android que
utilizar, y las caractersticas de hardware del dispositivo virtual, como por ejemplo su resolucin de pantalla o el
tamao de la tarjeta SD. Adems, se marcar la opcin Snapshot, que permitir arrancar el emulador ms
rpidamente en futuras ejecuciones.
Y con este paso ya se tienen preparadas todas las herramientas necesarias para comenzar a desarrollar
aplicaciones Android.
LECCION 2
Para crear un proyecto Android desde Eclipse se utiliza File -> New -> Project
Aparece una ventana de seleccin donde se indica Android y luego se escoge Android Application Project.
Manual Mca006
En la siguiente ventana se indica el nombre de la aplicacin, el nombre del proyecto y el paquete java que se
utilizara para las clases java. Se tiene que seleccionar adems la mnima versin del SDK que aceptar la
aplicacin al ser instalada en un dispositivo (Minimum Required SDK), la versin del SDK para la que se
desarrollara (Target SDK), y la versin del SDK con la que se compilara el proyecto (Compile with). Las dos ltimas
suelen coincidir con la versin de Android ms reciente. El resto de opciones se deja con los valores por defecto
Manual Mca006
Al pulsar el botn Next, se accede al siguiente paso del asistente, donde se tiene que indicar si durante la creacin
del nuevo proyecto se requiere crear un icono para la aplicacin (Create custom launcher icon) y si se requiere
crear una actividad inicial (Create activity). Tambin se puede indicar si el proyecto ser del tipo Librera (Mark this
Project as a library). En este primer ejemplo se dejan todas las opciones marcadas por defecto como se ve en la
siguiente imagen y se pulsa Next.
En la siguiente pantalla del asistente se configura el icono que tendr la aplicacin en el dispositivo. Se puede
seleccionar la imagen, texto o dibujo predefinido que aparecer en el icono, el margen, la forma y los colores
aplicados. En este ejemplo, se deja todo por defecto y se avanza al siguiente paso pulsando Next.
Manual Mca006
En la siguiente pantalla del asistente se elege el tipo de Actividad principal de la aplicacin. Una actividad es una
ventana o pantalla de la aplicacin. En este paso tambin se dejan todos los valores por defecto, indicando as
que la pantalla principal ser del tipo BlankActivity.
Por ltimo, en el ltimo paso del asistente se indican los datos de la actividad principal que se acaba de elegir,
indicando el nombre de su clase java asociada y el nombre de su layout xml (es la interfaz grfica de la actividad).
Manual Mca006
Una vez configurado todo, se pulsa el botn Finish y Eclipse crear toda la estructura del proyecto y los elementos
indispensables que debe contener. En la siguiente imagen se visualizan los elementos creados inicialmente para un
nuevo proyecto Android:
Carpeta /src/
Esta carpeta contendr todo el cdigo fuente de la aplicacin, cdigo de la interfaz grfica, clases auxiliares, etc.
Inicialmente, Eclipse crear el cdigo bsico de la pantalla (Activity) principal de la aplicacin, que en el ejemplo
era PpalActivity, y siempre bajo la estructura del paquete java definido.
Carpeta /res/
Contiene todos los archivos de recursos necesarios para el proyecto: imgenes, vdeos, cadenas de texto, etc. Los
diferentes tipos de recursos se distribuyen entre las siguientes subcarpetas:
Carpeta
Descripcin
10
Manual Mca006
/res/drawable/
/res/layout/
/res/anim/
/layout (vertical)
/layout-land (horizontal)
/res/animator/
/res/color/
/res/menu/
/res/xml/
/res/raw/
/res/values/
No todas estas carpetas tienen por qu aparecer en cada proyecto Android, tan slo las que se necesiten.
Como ejemplo, para un proyecto nuevo Android, se crean por defecto los siguientes recursos para la aplicacin:
11
Manual Mca006
Como se puede observar, existen algunas carpetas en cuyo nombre se incluye un sufijo adicional, como por
ejemplo values-v11 y values-v14. Estos, y otros sufijos, se emplean para definir recursos independientes para
determinados dispositivos segn sus caractersticas. De esta forma, por ejemplo, los recursos incluidos en la
carpeta values-v11 se aplicaran tan slo a dispositivos cuya versin de Android sea la 3.0 (API 11) o superior. Al
igual que el sufijo v existen otros muchos para referirse a otras caractersticas del terminal.
Entre los recursos creados por defecto, cabe destacar el layout activity_ppal.xml, que contiene la definicin de la
interfaz grfica de la pantalla principal de la aplicacin. Doble clic sobre el archivo, Eclipse mostrar esta interfaz
en su editor grfico (tipo arrastrar y soltar) y como se puede comprobar, en principio contiene tan slo una
etiqueta de texto centrada en pantalla con el mensaje Hello World!.
12
Manual Mca006
Existen dos maneras de trabajar, la primera utilizando el editor grfico, y la segunda manipulando directamente el
archivo XML asociado. En este caso, el XML asociado sera el siguiente:
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".PpalActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
Carpeta /gen/
Contiene una serie de elementos de cdigo generados automticamente al compilar el proyecto. Cada vez que se
genera el proyecto, la maquinaria de compilacin de Android genera automticamente una serie de archivos fuente
java dirigidos al control de los recursos de la aplicacin. Importante: dado que estos archivos se generan
automticamente tras cada compilacin del proyecto es importante que no se modifiquen manualmente bajo
ninguna circunstancia.
13
Manual Mca006
14
Manual Mca006
public static final int action_settings=0x7f080000;
}
public static final class layout {
public static final int activity_ppal=0x7f030000;
}
public static final class menu {
public static final int ppal=0x7f070000;
}
public static final class string {
public static final int action_settings=0x7f050001;
public static final int app_name=0x7f050000;
public static final int hello_world=0x7f050002;
}
public static final class style {
/**
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
API 11 theme customizations can go here.
Base application theme for API 14+. This theme completely replaces
AppBaseTheme from BOTH res/values/styles.xml and
res/values-v11/styles.xml on API 14+ devices.
API 14 theme customizations can go here.
*/
public static final int AppBaseTheme=0x7f060000;
/** Application theme.
All customizations that are NOT specific to a particular API-level can go here.
*/
public static final int AppTheme=0x7f060001;
}
}
Carpeta /assets/
Contiene todos los dems archivos auxiliares necesarios para la aplicacin (y que se incluirn en el paquete), como
por ejemplo archivos de configuracin, de datos, etc.
La diferencia entre los recursos incluidos en la carpeta /res/raw/ y los incluidos en la carpeta /assets/ es que para
los primeros se generar un ID en la clase R y se deber acceder a ellos con los diferentes mtodos de acceso a
recursos. Para los segundos sin embargo no se generarn IDs y se podr acceder a ellos por su ruta como a
cualquier otro archivo del sistema. Se utilizara uno u otro segn las necesidades de la aplicacin.
Carpeta /bin/
Contiene los elementos compilados de la aplicacin y los archivos auxiliares; es generada automticamente y no
debera ser modificada. Cabe destacar el archivo con extensin .apk, que es el ejecutable de la aplicacin que se
instalar en el dispositivo.
15
Manual Mca006
Carpeta /libs/
Contiene las libreras auxiliares, normalmente en formato .jar utilizadas en la aplicacin Android.
Archivo AndroidManifest.xml
Contiene la definicin en XML de los aspectos principales de la aplicacin, como por ejemplo su identificacin
(nombre, versin, icono, ), sus componentes (pantallas, mensajes, ), las libreras auxiliares utilizadas, o los
permisos necesarios para su ejecucin..
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="gala.curso"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="gala.curso.PpalActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
16
Manual Mca006
</manifest>
LECCION 3
A continuacin de enumeran los distintos tipos de componentes de software con los que se puede construir una
aplicacin Android.
En Java o .NET se manejan conceptos como ventana, control, eventos o servicios como los elementos bsicos en la
construccin de una aplicacin.
En Android se dispone tambin de esos mismos elementos bsicos aunque con un pequeo cambio en la
terminologa y el enfoque.
Activity
Las actividades (activities) representan el componente principal de la interfaz grfica de una aplicacin Android. Se
puede pensar en una actividad como el elemento anlogo a una ventana o pantalla en cualquier otro lenguaje
visual.
View
Las vistas (view) son los componentes bsicos con los que se construye la interfaz grfica de la aplicacin, anlogo
por ejemplo a los controles de Java o .NET. De inicio, Android pone a disposicin una gran cantidad de controles
bsicos, como cuadros de texto, botones, listas desplegables o imgenes, aunque tambin existe la posibilidad de
extender la funcionalidad de estos controles bsicos o crear nuevos controles personalizados.
Service
Los servicios (service) son componentes sin interfaz grfica que se ejecutan en segundo plano (background). En
concepto, son similares a los servicios presentes en cualquier otro sistema de operacin. Los servicios pueden
realizar cualquier tipo de acciones, por ejemplo actualizar datos, lanzar notificaciones, o incluso mostrar elementos
visuales (p.ej. actividades) si se necesita en algn momento la interaccin con del usuario.
Content Provider
Un proveedor de contenidos (content provider) es el mecanismo que se ha definido en Android para compartir
datos entre aplicaciones. Mediante estos componentes es posible compartir determinados datos de una aplicacin
sin mostrar detalles sobre su almacenamiento interno, su estructura, o su implementacin. De la misma forma,
una aplicacin podr acceder a los datos de otra a travs de los content provider que se hayan definido.
Broadcast Receiver
Un broadcast receiver es un componente destinado a detectar y reaccionar ante determinados mensajes o eventos
globales generados por el sistema (por ejemplo: Batera baja, SMS recibido, Tarjeta SD insertada, ) o por
otras aplicaciones (cualquier aplicacin puede generar mensajes (intents, en terminologa Android) broadcast, es
decir, no dirigidos a una aplicacin concreta sino a cualquiera que quiera escucharlo).
Widget
Los widgets son elementos visuales, normalmente interactivos, que pueden mostrarse en la pantalla principal
(home screen) del dispositivo Android y recibir actualizaciones peridicas. Permiten mostrar informacin de la
aplicacin al usuario directamente sobre la pantalla principal.
Intent
Un intent es el elemento bsico de comunicacin entre los distintos componentes Android descritos anteriormente.
Se pueden entender como los mensajes o peticiones que son enviados entre los distintos componentes de una
aplicacin o entre distintas aplicaciones. Mediante un intent se puede mostrar una actividad desde cualquier otra,
iniciar un servicio, enviar un mensaje broadcast, iniciar otra aplicacin, etc.
17
Manual Mca006
LECCION 4
A modo de ilustrar con un ejemplo, el desarrollo de aplicaciones en Android, se van a disear dos actividades, en la
primera se coloca un cdigo de curso y un botn con una accin de mostrar el valor introducido en la segunda
actividad.
La primera actividad se muestra en la siguiente figura:
El primer paso es es disear la pantalla principal. En Android, el diseo y la lgica de una pantalla estn separados
en dos arechvos distintos. Por un lado, en el archivo /res/layout/activity_ppal.xml se tiene el diseo puramente
visual de la pantalla definido como archivo XML y por otro lado, en el archivo /src/gala.curso/PpalActivity.java, se
encuentra el cdigo java que determina la lgica de la pantalla. A lo largo del manual se utilizaran estos archivos
en esto directorios, pero los nombres pueden ser cambiados a gusto de los desarrolladores.
Se va a modificar en primer lugar el aspecto de la ventana principal de la aplicacin aadiendo los controles
(views) requeridos. Para ello, se edita el contenido del archivo activity_ppal.xml por el siguiente:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LLPpal"
android:layout_width="match_parent"
android:layout_height="match_parent"
18
Manual Mca006
android:orientation="vertical" >
<TextView
android:id="@+id/TvCurso"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/curso" />
<EditText
android:id="@+id/EtCurso"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text">
</EditText>
<Button
android:id="@+id/BBienvenido"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bienvenido" />
</LinearLayout>
En este XML se definen los elementos visuales que componen la interfaz de la pantalla principal y se especifican
todas sus propiedades.
El primer elemento es LinearLayout. Los layout son elementos no visibles que determinan cmo se van a distribuir
en el espacio los controles incluidos en su interior. Los programadores java, y ms concretamente de Swing,
conocen este concepto perfectamente. En este caso, un LinearLayout distribuir los controles simplemente uno
tras otro y en la orientacin que indique su propiedad android:orientation, que en este caso ser vertical.
Dentro del layout se incluyen 3 controles: una etiqueta (TextView), un cuadro de texto (EditText), y un botn
(Button). En todos ellos se han establecido las siguientes propiedades:
android:id. ID del control, con el que se podr identificarlo ms tarde en el cdigo. El identificador se escribe
precedido de @+id/. Esto tendr como efecto que al compilarse el proyecto se genere automticamente una
nueva constante en la clase R para dicho control. As, por ejemplo, como el cuadro de texto tiene el ID EtCurso, se
puede ms tarde acceder a l desde el cdigo referenciando la constante R.id.EtCurso.
android:layout_height y android:layout_width. Dimensiones del control con respecto al layout que lo
contiene. Esta propiedad tomar normalmente los valores wrap_content para indicar que las dimensiones del
control se ajustarn al contenido del mismo, o bien match_parent para indicar que el ancho o el alto del control
se ajustar al ancho o alto del layout contenedor respectivamente.
Adems de estas propiedades comunes a casi todos los controles, en el cuadro de texto se establece tambin la
propiedad android:inputType, que indica qu tipo de contenido va a albergar el control, en este caso texto
normal (valor text), aunque podra haber sido una contrasea (textPassword), un telfono (phone), una fecha
(date), .
Por ltimo, en la etiqueta y el botn se ha establecido la propiedad android:text, que indica el texto que aparece
en el control. Se tienen dos alternativas a la hora de hacer esto. En Android, el texto de un control se puede
especificar directamente como valor de la propiedad android:text, o bien utilizar alguna de las cadenas de texto
definidas en los recursos del proyecto (en el archivo strings.xml), en cuyo caso se indica como valor de la
propiedad android:text su identificador precedido del prefijo @string/. Dicho de otra forma, la primera alternativa
habra sido indicar directamente el texto como valor de la propiedad, por ejemplo en la etiqueta de esta forma:
<TextView
android:id="@+id/TvCurso"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Indique el codigo del curso: " />
19
Manual Mca006
Y la segunda alternativa, la utilizada en el ejemplo, consistira en definir primero una nueva cadena de texto en el
archivo de recursos /res/values/strings.xml, por ejemplo con identificador curso y valor Indique el cdigo del
curso :.
</resources>
Y posteriormente indicar el identificador de la cadena como valor de la propiedad android:text, siempre precedido
del prefijo @string/, de la siguiente forma:
<TextView
android:id="@+id/TvCurso"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/curso" />
Esta segunda alternativa permite tener perfectamente localizadas y agrupadas todas las cadenas de texto
utilizadas en la aplicacin, lo que podra facilitar por ejemplo la traduccin de la aplicacin a otro idioma.
A continuacin se define la interfaz de la segunda pantalla, creando un nuevo archivo llamado
activity_bienvenido.xml, y aadiendo esta vez tan solo una etiqueta (TextView) para mostrar el mensaje
personalizado de bienvenida al usuario.
Para aadir el archivo, se pulsa el botn derecho del ratn sobre la carpeta de recursos /res/layout y se pulsa la
opcin New Android XML file.
En el cuadro de dilogo que aparece se indica como tipo de recurso Layout, se indica el nombre del archivo (con
extensin .xml) y como elemento raz se seleccion LinearLayout. Finalmente se pulsa Finish para crear el archivo.
Eclipse crear entonces el nuevo archivo y lo abrir en el editor grfico, aunque se acceder a la pestaa de cdigo
para modificar directamente el contenido XML del archivo.
Para esta segunda pantalla el cdigo del archivo es el siguiente :
<?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" >
<TextView
android:id="@+id/TvBienvenido"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
</LinearLayout>
Una vez definida la interfaz de las pantallas de la aplicacin se debe implementar la lgica de la misma. Como ya
se ha comentado, la lgica de la aplicacin se definir en archivos java independientes. Para la pantalla principal el
archivo se llama PpalActivity.java. La documentacin en el cdigo indica los pasos seguidos en la implementacin
del ejemplo.
package gala.curso;
20
Manual Mca006
// Clases requeridas
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.content.Intent;
public class PpalActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// cdigo defecto
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ppal);
// Ubicacion de los controles en la actividad
final EditText etCurso = (EditText)findViewById(R.id.EtCurso);
final Button bBienvenido = (Button)findViewById(R.id.BBienvenido);
// Implementacion del Listener del Boton, para escuchar sus eventos
bBienvenido.setOnClickListener(new OnClickListener() {
@Override
// Implementacion del evento onClick
public void onClick(View v) {
// Crear el Intent para comunicar la Principal con Bienvenido
Intent intent =
new Intent(PpalActivity.this, BienvenidoActivity.class);
// Crear la informacin a pasar entre actividades
Bundle b = new Bundle();
b.putString("CURSO", etCurso.getText().toString());
//Aadir la informacin al intent
intent.putExtras(b);
//Iniciar la nueva actividad
startActivity(intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.ppal, menu);
return true;
}
}
Las diferentes pantallas de una aplicacin Android se definen mediante objetos de tipo Activity. Por tanto, lo
primero que se encuentra en el archivo java es la definicin de una clase PpalActivity que extiende a Activity. El
mtodo onCreate(), se invoca cuando se crea por primera vez la actividad. En este mtodo se encuentra en
principio, adems de la llamada a su implementacin en la clase padre, es la llamada al mtodo
setContentView(R.layout.activity_ppal). Con esta llamada se esta indicando a Android que debe establecer como
interfaz grfica de esta actividad la definida en el recurso R.layout.activity_ppal, que no es ms que la que se ha
especificado en el archivo /res/layout/activity_main.xml. Una vez ms se observa la utilidad de las diferentes
constantes de recursos creadas automticamente en la clase R al compilar el proyecto.
21
Manual Mca006
Adems del mtodo onCreate(),tambin se sobrescribe el mtodo onCreateOptionsMenu(), que se utiliza para
definir mens en la aplicacin.
Para crear una nueva actividad para la segunda pantalla de la aplicacin anloga a sta primera, se crea una nueva
clase BienvenidoActivity que extiende tambin de Activity y que implemente el mtodo onCreate() pero indicando
esta vez que utilice la interfaz definida para la segunda pantalla en R.layout.activity_bienvenido.
Para ello, se pulsa el botn derecho sobre la carpeta /src/gala.curso/ y se selecciona la opcin de men New /
Class.
En el cuadro de dilogo que aparece se indicaremos el nombre (Name) de la nueva clase y su clase padre
(Superclass) como android.app.Activity.
Se pulsar Finish y Eclipse crear el nuevo archivo y lo abrir en el editor de cdigo java, all se coloca el siguiente
cdigo:
package gala.curso;
// clases a utilizar
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
}
}
NOTA: Todos los pasos anteriores de creacin de una nueva pantalla (layout xml + clase java) se puede realizar
tambin mediante un asistente de Eclipse al que se accede mediante el men contextual New / Other / Android /
Android Activity.
Una vez concluido la lgica de las dos pantallas de la aplicacin, slo queda un paso importante para finalizar el
desarrollo. Toda aplicacin Android utiliza un archivo especial en formato XML (AndroidManifest.xml) para
definir, entre otras cosas, los diferentes elementos que la componen. Por tanto, todas las actividades de la
aplicacin deben quedar convenientemente recogidas en este arechivo. La actividad principal ya debe aparecer
puesto que se cre de forma automtica al crear el nuevo proyecto Android, por lo que se debe aadir tan slo la
segunda.
22
Manual Mca006
Para este ejemplo se limita a incluir la actividad en el XML mediante una nueva etiqueta <Activity>, indicar el
nombre de la clase java asociada como valor del atributo android:name, y asignarle su ttulo mediante el atributo
android:label. Todo esto se incluye justo debajo de la definicin de la actividad principal dentro del archivo
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="gala.curso"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="gala.curso.PpalActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="gala.curso.BienvenidoActivity"
android:label="@string/activity_bienvenido" >
</activity>
</application>
</manifest>
LECCION 5
Los layouts son elementos no visuales destinados a controlar la distribucin, posicin y dimensiones de los
controles que se insertan en su interior. Estos componentes extienden a la clase base ViewGroup, como muchos
otros componentes contenedores, es decir, capaces de contener a otros controles.
FrameLayout
ste es el ms simple de todos los layouts de Android. Un FrameLayout coloca todos sus controles hijos alineados
con su esquina superior izquierda, de forma que cada control quedar oculto por el control siguiente (a menos que
ste ltimo tenga transparencia). Por ello, suele utilizarse para mostrar un nico control en su interior, a modo de
contenedor (placeholder) sencillo para un slo elemento sustituible, por ejemplo una imagen.
Los componentes incluidos en un FrameLayout podrn establecer sus propiedades android:layout_width y
android:layout_height, que podrn tomar los valores match_parent (para que el control hijo tome la
dimensin de su layout contenedor) o wrap_content (para que el control hijo tome la dimensin de su
contenido). NOTA: Si se est utilizando una versin de la API de Android inferior a la 8 (Android 2.2), en vez de
match_parent se deber utilizar su equivalente fill_parent.
Ejemplo
<FrameLayout
23
Manual Mca006
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText android:id="@+id/TxtNombre"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="text" />
</FrameLayout>
Con el cdigo anterior se consigue un layout tan sencillo como el siguiente:
LinearLayout
El siguiente tipo de layout en cuanto a nivel de complejidad es el LinearLayout. Este layout apila uno tras otro
todos sus elementos hijos de forma horizontal o vertical segn se establezca su propiedad android:orientation.
Al igual que en un FrameLayout, los elementos contenidos en un LinearLayout pueden establecer sus propiedades
android:layout_width y android:layout_height para determinar sus dimensiones dentro del layout. Pero en el
caso de un LinearLayout, se tiene otro parmetro con el que jugar, la propiedad android:layout_weight.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
24
Manual Mca006
<EditText android:id="@+id/TxtNombre"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button android:id="@+id/BtnAceptar"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
Esta propiedad permite dar a los elementos contenidos en el layout unas dimensiones proporcionales entre ellas. Si
se incluye en un LinearLayout vertical dos cuadros de texto (EditText) y a uno de ellos se le establece un
layout_weight=1 y al otro un layout_weight=2 se consigue como efecto que toda la superficie del layout quede
ocupada por los dos cuadros de texto y que adems el segundo sea el doble (relacin entre sus propiedades
weight) de alto que el primero.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText android:id="@+id/TxtDato1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="text"
android:layout_weight="1" />
<EditText android:id="@+id/TxtDato2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="text"
android:layout_weight="2" />
25
Manual Mca006
</LinearLayout>
Con el cdigo anterior se consigue un layout como el siguiente:
As pues, a pesar de la simplicidad aparente de este layout resulta ser lo suficiente verstil como para ser de
utilidad en muchas ocasiones.
TableLayout
Un TableLayout permite distribuir sus elementos hijos de forma tabular, definiendo las filas y columnas necesarias,
y la posicin de cada componente dentro de la tabla.
La estructura de la tabla se define de forma similar a como se hace en HTML, es decir, indicando las filas que
compondrn la tabla (objetos TableRow), y dentro de cada fila las columnas necesarias, con la salvedad de que
no existe ningn objeto especial para definir una columna (algo as como un TableColumn) sino que directamente
se insertan los controles necesarios dentro del TableRow y cada componente insertado (que puede ser un control
sencillo o incluso otro ViewGroup) corresponder a una columna de la tabla. De esta forma, el nmero final de filas
de la tabla se corresponder con el nmero de elementos TableRow insertados, y el nmero total de columnas
quedar determinado por el nmero de componentes de la fila que ms componentes contenga.
Por norma general, el ancho de cada columna se corresponder con el ancho del mayor componente de dicha
columna, pero existen una serie de propiedades para modificar este comportamiento:
android:stretchColumns. Indicar las columnas que pueden expandir para absorber el espacio libre dejado por
las dems columnas a la derecha de la pantalla.
android:shrinkColumns. Indicar las columnas que se pueden contraer para dejar espacio al resto de columnas
que se puedan salir por la derecha de la pantalla.
android:collapseColumns. Indicar las columnas de la tabla que se quieren ocultar completamente.
Todas estas propiedades del TableLayout pueden recibir una lista de ndices de columnas separados por comas
(ejemplo: android:stretchColumns=1,2,3) o un asterisco para indicar que debe aplicar a todas las columnas
(ejemplo: android:stretchColumns=*).
Otra caracterstica importante es la posibilidad de que una celda determinada pueda ocupar el espacio de varias
columnas de la tabla (anlogo al atributo colspan de HTML). Esto se indicar mediante la propiedad
android:layout_span del componente concreto que deber tomar dicho espacio.
A continuacin se muestra un ejemplo.
<TableLayout
26
Manual Mca006
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow>
<TextView android:text="Celda 1.1" />
<TextView android:text="Celda 1.2" />
<TextView android:text="Celda 1.3" />
</TableRow>
<TableRow>
<TextView android:text="Celda 2.1" />
<TextView android:text="Celda 2.2" />
<TextView android:text="Celda 2.3" />
</TableRow>
<TableRow>
<TextView android:text="Celda 3.1"
android:layout_span="2" />
<TextView android:text="Celda 3.2" />
</TableRow>
</TableLayout>
El layout resultante del cdigo anterior sera el siguiente:
27
Manual Mca006
GridLayout
Este tipo de layout fue incluido a partir de la API 14 (Android 4.0) y sus caractersticas son similares al
TableLayout, ya que se utiliza igualmente para distribuir los diferentes elementos de la interfaz de forma tabular,
distribuidos en filas y columnas. La diferencia entre ellos estriba en la forma que tiene el GridLayout de colocar y
distribuir sus elementos hijos en el espacio disponible. En este caso, a diferencia del TableLayout se indica el
nmero de filas y columnas como propiedades del layout, mediante android:rowCount y android:columnCount.
Con estos datos ya no es necesario ningn tipo de elemento para indicar las filas, como se haca con el elemento
TableRow del TableLayout, sino que los diferentes elementos hijos se irn colocando ordenadamente por filas o
columnas (dependiendo de la propiedad android:orientation) hasta completar el nmero de filas o columnas
indicadas en los atributos anteriores. Adicionalmente, igual que en el caso anterior, tambin se tienen disponibles
las propiedades android:layout_rowSpan y android:layout_columnSpan para conseguir que una celda ocupe
el lugar de varias filas o columnas.
Existe tambin una forma de indicar de forma explcita la fila y columna que debe ocupar un determinado elemento
hijo contenido en el GridLayout, y se consigue utilizando los atributos android:layout_row y
android:layout_column. De cualquier forma, salvo para configuraciones complejas del grid no suele ser
necesario utilizar estas propiedades.
Con todo esto en cuenta, para conseguir una distribucin equivalente a la del ejemplo anterior del TableLayout, se
necesitara escribir un cdigo como el siguiente:
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:rowCount="2"
android:columnCount="3"
android:orientation="horizontal" >
28
Manual Mca006
</GridLayout>
RelativeLayout
Este layout permite especificar la posicin de cada elemento de forma relativa a su elemento padre o a cualquier
otro elemento incluido en el propio layout. De esta forma, al incluir un nuevo elemento X se puede indicar por
ejemplo que debe colocarse debajo del elemento Y y alineado a la derecha del layout padre.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<EditText android:id="@+id/TxtNombre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text" />
<Button android:id="@+id/BtnAceptar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/TxtNombre"
android:layout_alignParentRight="true" />
</RelativeLayout>
29
Manual Mca006
Al igual que estas tres propiedades, en un RelativeLayout se tiene un sinfn de propiedades para colocar cada
control justo donde se requiere A continuacin se indican:
Posicin relativa a otro control:
android:layout_above.
android:layout_below.
android:layout_toLeftOf.
android:layout_toRightOf.
android:layout_alignLeft.
android:layout_alignRight.
android:layout_alignTop.
android:layout_alignBottom.
android:layout_alignBaseline.
android:layout_alignParentLeft.
android:layout_alignParentRight.
android:layout_alignParentTop.
android:layout_alignParentBottom.
android:layout_centerHorizontal.
android:layout_centerVertical.
android:layout_centerInParent.
android:layout_margin.
android:layout_marginBottom.
android:layout_marginTop.
android:layout_marginLeft.
android:layout_marginRight.
30
Manual Mca006
Opciones de espaciado o padding (tambin disponibles para el resto de layouts):
android:padding.
android:paddingBottom.
android:paddingTop.
android:paddingLeft.
android:paddingRight.
LECCION 6
Los controles en Android se parametrizan indicando las Propiedade y se personalizan programando los eventos. Las
propiedades de apariencia pueden definirse en los archivos .xml donde se indican los layouts para los recursos. Las
propiedades y los eventos pueden programarse dinmicamente en las clases de Java.
Por ejemplo, el siguiente archivo .xml define las propiedades de tres controles, uno del tipo TextView (etiqueta),
uno del tipo EditText(caja de texto) y uno del tipo Button (button).
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LLPpal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/TvCurso"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/curso" />
<EditText
android:id="@+id/EtCurso"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text">
</EditText>
<Button
android:id="@+id/BBienvenido"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bienvenido" />
</LinearLayout>
La propiedad id, define el identificador nico del control y como se puede acceder a l desde cualquier lugar del
cdigo. Al indicar el prefijo @+id/ al id del control se le indica al compilador de Java que lo coloque como una
constante en la clase R.
public static final
public static
public static
public static
public static
}
class id {
final int BBienvenido=0x7f080004;
final int EtCurso=0x7f080003;
final int LLPpal=0x7f080001;
final int TvCurso=0x7f080002;
31
Manual Mca006
El cdigo de los eventos se escribe siguiendo el formato de los Listener definidos en Java, dentro de un Listener se
colocan todos los eventos a manejarse por el control.
bBienvenido.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Crear el Intent para comunicar la Principal con Bienvenido
Intent intent =
new Intent(PpalActivity.this, BienvenidoActivity.class);
// Crear la informacin a pasar entre actividades
Bundle b = new Bundle();
b.putString("CURSO", etCurso.getText().toString());
//Aadir la informacin al intent
intent.putExtras(b);
//Iniciar la nueva actividad
startActivity(intent);
}
});
El ejemplo anterior muestra cmo implementar el evento onClick para el botn bBienvenido de un control del tipo
Button. Cada evento se encuentra asociado a un Listener. De esta manera se personaliza el cdigo de los
controles. Para la clase botn existe el mtodo setOnClickListener y el evento OnClick en cual se implementa como
un mtodo de la clase OnClickListener.
Personalizar el aspecto de un control
Para cambiar la forma de un botn se podra simplemente asignar una imagen a la propiedad
android:background, pero esta solucin no sirve de mucho porque siempre se mostrara la misma imagen
incluso con el botn pulsado, dando poca sensacin de elemento clickable.
La solucin perfecta pasara por tanto por definir diferentes imgenes de fondo dependiendo del estado del botn.
Pues bien, Android ofrece total libertad para hacer esto mediante el uso de selectores. Un selector se define
mediante un archivo XML localizado en la carpeta /res/drawable, y en l se pueden establecer los diferentes
valores de una propiedad determinada de un control dependiendo de su estado.
Por ejemplo, si se requiere dar un aspecto plano a un botn ToggleButton, se puede disear las imgenes
necesarias para los estados pulsado (toggle_on.png) y no pulsado (toggle_off.png) y crear un selector como el
siguiente:
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="@drawable/toggle_off" />
<item android:state_checked="true"
32
Manual Mca006
android:drawable="@drawable/toggle_on" />
</selector>
En el cdigo anterior se asigna a cada posible estado del botn una imagen (un elemento drawable) determinado.
As, por ejemplo, para el estado pulsado (state_checked=true) se asigna la imagen toggle_on.
Este selector se guarda por ejemplo en un archivo llamado toggle_style.xml y se coloca como un recurso ms en la
carpeta de recursos /res/drawable. Hecho esto, tan slo basta hacer referencia a este nuevo recurso creado en
la propiedadandroid:background del botn:
<ToggleButton android:id="@+id/BtnBoton4"
android:textOn="@string/on"
android:textOff="@string/off"
android:padding="10dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/toggle_style"/>
En la siguiente imagen se visualiza el aspecto por defecto de un ToggleButton (columna izquierda) y cmo ha
quedado el ToggleButton personalizado (columna derecha).
33
Manual Mca006
Un control de tipo Button es el botn ms bsico a utilizar. En el ejemplo siguiente se define un botn con el texto
Pulsar asignando su propiedad android:text. Adems de esta propiedad se podra utilizar muchas otras como el
color de fondo (android:background), estilo de fuente (android:typeface), color de fuente
(android:textcolor), tamao de fuente (android:textSize), etc.
<Button android:id="@+id/BBoton1"
android:text="@string/Pulsar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Un control de tipo ToggleButton es un tipo de botn que puede permanecer en dos posibles estados,
pulsado/no_pulsado. En este caso, en vez de definir un slo texto para el control se definen dos, dependiendo de
su estado. As, se pueden asignar las propiedades android:textOn y android:textoOff para definir ambos textos.
<ToggleButton android:id="@+id/BBoton2"
android:textOn="@string/on"
android:textOff="@string/off"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageButton android:id="@+id/BBoton3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
34
Manual Mca006
android:contentDescription="@string/icono_ok"
android:src="@drawable/ok" />
Aunque existe este tipo especfico de botn para imgenes, tambin es posible aadir una imagen a un botn
normal de tipo Button, a modo de elemento suplementario al texto. Por ejemplo, si se requiere aadir un icono a la
izquierda del texto de un botn se utiliza la propiedad android:drawableLeft indicando como valor el descriptor
(ID) de la imagen que se requiere mostrar:
<Button android:id="@+id/BBoton5"
android:text="@string/pulsar"
android:drawableLeft="@drawable/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView android:id="@+id/IVFoto"
android:layout_width="wrap_content"
35
Manual Mca006
android:layout_height="wrap_content"
android:src="@drawable/icon"
android:contentDescription="@string/imagen_ejemplo" />
Si en vez de establecer la imagen a mostrar en el propio layout XML de la actividad se requiere establecer
mediante cdigo se utiliza el mtodo setImageResorce(), pasndo el ID del recurso a utilizar como contenido de
la imagen.
iv.setImageResource(R.drawable.icon);
El control TextView (Etiquetas) es otro de los clsicos en la programacin de GUIs, las etiquetas de texto, y se
utiliza para mostrar un determinado texto al usuario. Al igual que en el caso de los botones, el texto del control se
establece mediante la propiedad android:text. A parte de esta propiedad, la naturaleza del control hace que las
ms interesantes sean las que establecen el formato del texto mostrado, que al igual que en el caso de los botones
son las siguientes: android:background (color de fondo), android:textColor (color del texto),
android:textSize (tamao de la fuente) y android:typeface (estilo del texto: negrita, cursiva, ).
<TextView android:id="@+id/LEtiqueta"
android:layout_width="matchfill_parent"
android:layout_height="wrap_content"
android:background="#AA44FF"
android:typeface="monospace" />
De igual forma, tambin es posible manipular estas propiedades desde el cdigo. Como ejemplo, en el siguiente
fragmento se recupera el texto de una etiqueta con getText(), y posteriormente se concatenan unos nmeros, y
se actualiza su contenido mediante setText() y se le cambia su color de fondo con setBackgroundColor().
36
Manual Mca006
texto += "123";
lEtiqueta.setText(texto);
lEtiqueta.setBackgroundColor(Color.BLUE);
El control EditText (Caja de Texto) es el componente de edicin de texto que proporciona la plataforma Android.
Permite la introduccin y edicin de texto por parte del usuario, por lo que en tiempo de diseo la propiedad ms
interesante a establecer, adems de su posicin/tamao y formato, es el texto a mostrar, atributo android:text.
Por supuesto si no se requiere que el cuadro de texto aparezca inicializado con ningn texto, no es necesario incluir
esta propiedad en el layout XML. Si se debe establecer la propiedad android:inputType. Esta propiedad indica el
tipo de contenido que se va a introducir en el cuadro de texto, como por ejemplo una direccin de correo
electrnico (textEmailAddress), un nmero genrico (number), un nmero de telfono (phone), una direccin
web (textUri), o un texto genrico (text). El valor que se establece para esta propiedad tendr adems efecto en
el tipo de teclado que mostrar Android para editar dicho campo. As, por ejemplo, si se indicado text mostrar el
teclado completo alfanumrico, si se indicado phone mostrar el teclado numrico del telfono, etc.
<EditText android:id="@+id/ETTexto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text" />
De igual forma, desde el cdigo se puede recuperar y establecer el texto mediante los mtodos getText() y
setText(nuevoTexto) respectivamente:
final EditText ETTexto = (EditText)findViewById(R.id.ETTexto);
String texto = ETTexto.getText().toString();
ETTexto.setText("Bienvenido!");
Notar que es necesario realizar una llamada toString() al resultado de getText(). La explicacin para esto es que el
mtodo getText() no devuelve directamente una cadena de caracteres (String) sino un objeto de tipo Editable, que
a su vez implementa la interfaz Spannable. Y esto demuestra caracterstica ms interesante del control EditText, y
es que no slo permite editar texto plano sino tambin texto enriquecido o con formato.
Interfaz Spanned
Un objeto de tipo Spanned es una cadena de caracteres (deriva de la interfaz CharSequence) en la que se pueden
insertar otros objetos a modo de marcas o etiquetas(spans) asociados a rangos de caracteres. De esta interfaz
deriva la interfaz Spannable, que permite la modificacin de estas marcas, y a su vez de sta ltima deriva la
interfaz Editable, que permite adems la modificacin del texto.
37
Manual Mca006
De esta manera se pueden insertar marcas de formato de texto, as como cualquier tipo de objeto.
Existen muchos tipos de spans predefinidos en la plataforma que se pueden utilizar para dar formato al texto, entre
ellos:
De esta forma, para crear un nuevo objeto Editable e insertar una marca de formato se puede hacer lo siguiente:
// Se crea un nuevo objeto de tipo Editable
Editable str = Editable.Factory.getInstance().newEditable("Esto es un simulacro.");
//Se marca cono fuente negrita la palabra "simulacro" (caracteres del 11-19)
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 11, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
En este ejemplo se est insertando un span de tipo StyleSpan para marcar un fragmento de texto con estilo
negrita. Para insertarlo se utilizael mtodo setSpan(), que recibe como parmetro el objeto Span a insertar, la
posicin inicial y final del texto a marcar, y un flag que indica la forma en la que el span se podr extender al
insertarse nuevo texto.
Texto con formato en controles TextView y EditText
Con el mtodo setText se pueden asignar objetos Editables a los controles TextView y EditText. Por ejemplo si
se le asigna al control EditText el objeto Editable creado en los ejemplos:
ETTexto.setText(str);
Tras ejecutar el cdigo, insertando un botn SetText en la aplicacin de ejemplo, se observa como efectivamente
en el cuadro de texto aparece el mensaje con el formato esperado:
En la aplicacin de ejemplo tambin se incluye un botn adicional Negrita que se encargar de convertir a estilo
negrita un fragmento de texto previamente seleccionado en el cuadro de texto. La intencin deesto es presentar
los mtodos disponibles para determinar el comienzo y el fin de una seleccin en un control de este tipo. Para ello
se utilizan los mtodos getSelectionStart() y getSelectionEnd(), que devuelven el ndice del primer y ltimo
carcter seleccionado en el texto. Sabiendo esto, slo queda utilizar el mtodo setSpan() para convertir la
seleccin a negrita.
Spannable texto = ETTexto.getText();
38
Manual Mca006
int ini = ETTexto.getSelectionStart();
int fin = ETTexto.getSelectionEnd();
texto.setSpan(
new StyleSpan(android.graphics.Typeface.BOLD),
ini, fin,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
En Andriod es posible asignar texto con y sin formato a un cuadro de texto, pero qu ocurre a la hora de
recuperar texto con formato desde el control?. La funcin getText() devuelve un objeto de tipo Editable y sobre
ste se puede hacer un toString(). Pero con esta solucin se est perdiendo todo el formato del texto, y no se
podra por ejemplo salvar en una base de datos.
La solucin a esto ltimo requiere recuperar directamente el objeto Editable y serializarlo de algn modo, mejor
an si es en un formato estandar. En Android este trabajo lo realiza la clase Html
http://developer.android.com/reference/android/text/Html, con mtodos para convertir cualquier objeto Spanned
en su representacin HTML equivalente. En el siguiente ejemplo se recupera el texto de la ventana anterior y se
utilicemos el mtodo Html.toHtml(Spannable) para convertirlo a formato HTML:
//Obtiene el texto del control con etiquetas de formato HTML
String aux2 = Html.toHtml(ETTexto.getText());
Haciendo esto, se obtendra una cadena de texto como la siguiente, la cual se podra por ejemplo almacenar en
una base de datos o publicar en cualquier web sin perder el formato de texto establecido:
<p>Esto es un <b>simulacro</b></p>
La operacin contraria tambin es posible, es decir, cargar un cuadro de texto de Android (EditText) o una etiqueta
(TextView) a partir de un fragmento de texto en formato HTML. Para ello se puede utilizar el mtodo
Html.fromHtml(String) de la siguiente forma:
//Asigna texto con formato HTML
ETTexto.setText(
Html.fromHtml("<p>Esto es un <b>simulacro</b>.</p>"),
BufferType.SPANNABLE);
Control CheckBox http://developer.android.com/reference/android/widget/CheckBox.html
Un control checkbox se suele utilizar para marcar o desmarcar opciones en una aplicacin, y en Android est
representado por la clase del mismo nombre, CheckBox. La forma de definirlo en la interfaz y los mtodos
disponibles para manipularlos desde el cdigo son anlogos a los ya indicados para el control ToggleButton.
De esta forma, para definir un control de este tipo en el layout se puede utilizar el cdigo siguiente, que define un
checkbox con el texto Marcar:
<CheckBox android:id="@+id/CBMarcar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/marcar"
39
Manual Mca006
android:checked="false" />
En cuanto a la personalizacin del control se puede decir que ste extiende [indirectamente] del control TextView,
por lo que todas las opciones de formato son vlidas tambin para este control. Adems, se puede utilizar la
propiedad android:checked para inicializar el estado del control a marcado (true) o desmarcado (false). Si no se
establece esta propiedad el control aparecer por defecto en estado desmarcado.
En el cdigo de la aplicacin se puede hacer uso de los mtodos isChecked() para conocer el estado del control, y
setChecked(estado) para establecer un estado concreto para el control.
if (checkBox.isChecked()) {
checkBox.setChecked(false);
}
En cuanto a los posibles eventos que puede lanzar este control, el ms interesante, al margen del siempre vlido
onClick, es sin duda el que informa de que ha cambiado el estado del control, que recibe el nombre de
onCheckedChanged. Para implementar las acciones de este evento se utiliza la siguiente lgica, donde tras
capturar el evento, y dependiendo del nuevo estado del control (variable isChecked recibida como parmetro), se
realiza una accin
private CheckBox cbMarcar;
//...
cbMarcar = (CheckBox)findViewById(R.id.CBMarcar);
cbMarcar.setOnCheckedChangeListener(
new CheckBox.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
cbMarcar.setText("Checkbox marcado!");
}
else {
cbMarcar.setText("Checkbox desmarcado!");
}
}
});
Control RadioButton http://developer.android.com/reference/android/widget/RadioButton.html
Al igual que los controles checkbox, un radiobutton puede estar marcado o desmarcado, pero en este caso
suelen utilizarse dentro de un grupo de opciones donde una, y slo una, de ellas debe estar marcada
obligatoriamente, es decir, que si se marca una de las opciones se desmarcar automticamente la que estuviera
activa anteriormente. En Android, un grupo de botones radiobutton se define mediante un elemento
RadioGroup, que a su vez contendr todos los elementos RadioButton necesarios. Un ejemplo de cmo definir un
grupo de dos controles radiobutton en la interfaz:
40
Manual Mca006
<RadioGroup android:id="@+id/RGgruporb"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RadioButton android:id="@+id/RBradio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/opcion_1" />
<RadioButton android:id="@+id/RBradio2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/opcion_2" />
</RadioGroup>
En primer lugar se puede definir el grupo de controles indicando su orientacin (vertical u horizontal) al igual que
ocurra por ejemplo con un LinearLayout. Tras esto, se aaden todos los objetos RadioButton necesarios indicando
su ID mediante la propiedad android:id y su texto mediante android:text.
Una vez definida la interfaz se puede manipular el control desde el cdigo java haciendo uso de los diferentes
mtodos del control RadioGroup, los ms importantes: check(id) para marcar una opcin determinada mediante
su ID, clearCheck() para desmarcar todas las opciones, y getCheckedRadioButtonId() que como su nombre
indica devolver el ID de la opcin marcada (o el valor -1 si no hay ninguna marcada).
RadioGroup rg = (RadioGroup)findViewById(R.id.RGgruporb);
rg.clearCheck();
rg.check(R.id.RBradio1);
int idSeleccionado = rg.getCheckedRadioButtonId();
En cuanto a los eventos disparados, a parte de onClick, al igual que en el caso de los checkboxes, el ms
importante ser el que informa de los cambios en el elemento seleccionado, llamado tambin en este caso
onCheckedChange.Este evento del objeto RadioGroup, se muestra con un ejemplo de una etiqueta de texto que
cambia de valor al seleccionar cada opcin.
private TextView lblMensaje;
private RadioGroup rgOpciones;
//...
41
Manual Mca006
lblMensaje = (TextView)findViewById(R.id.LSeleccion);
rgOpciones = (RadioGroup)findViewById(R.id.RGgruporb);
rgOpciones.setOnCheckedChangeListener(
new RadioGroup.OnCheckedChangeListener() {
public void onCheckedChanged(RadioGroup group, int checkedId) {
lblMensaje.setText("ID opcin seleccionada: " + checkedId);
}
});
LECCION 8 Controles de Seleccin: Adaptadores, Listas desplegables tipo Spinner, Listas fijas tipo
ListView, GridView
Al igual que en otros frameworks Android dispone de diversos controles para seleccionar una opcin dentro de una
lista de posibilidades. As, se puede utilizar listas desplegables (Spinner), listas fijas (ListView), tablas
(GridView) y otros controles especficos de la plataforma como por ejemplo las galeras de imgenes (Gallery).
Los controles de seleccin utilizan un elemento importante y comn a todos ellos, los adaptadores.
Adaptadores en Android (adapters)
Para los desarrolladores de java que hayan utilizado frameworks de interfaz grfica como Swing, el concepto de
adaptador les resultar familiar. Un adaptador representa una interfaz comn al modelo de datos que existe por
detrs de todos los controles de seleccin. Por lo tanto, todos los controles de seleccin accedern a los datos que
contienen a travs de un adaptador.
Adems de proveer de datos a los controles visuales, el adaptador tambin ser responsable de generar a partir de
estos datos las vistas especficas que se mostrarn dentro del control de seleccin. Por ejemplo, si cada elemento
de una lista estuviera formado a su vez por una imagen y varias etiquetas, el responsable de generar y establecer
el contenido de todos estos sub-elementos a partir de los datos ser el propio adaptador.
Android proporciona de serie varios tipos de adaptadores sencillos, aunque se puede extender su funcionalidad
facilmente para adaptarlos a los requerimientos. Los ms comunes son los siguientes:
SimpleAdapter. Se utiliza para mapear datos sobre los diferentes controles definidos en un archivo XML
de layout.
SimpleCursorAdapter. Se utiliza para mapear las columnas de un cursor abierto sobre una base de
datos sobre los diferentes elementos visuales contenidos en el control de seleccin.
A continuacin se crea un adaptador de tipo ArrayAdapter para trabajar con un array genrico de java:
final String[] datos =
new String[]{"Elem1","Elem2","Elem3","Elem4","Elem5"};
42
Manual Mca006
ArrayAdapter<String> adaptador =
new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, datos);
Para crear un adaptador se requieren tres parmetros:
El contexto, que normalmente ser simplemente una referencia a la actividad donde se crea el adaptador.
El ID del layout sobre el que se mostrarn los datos del control. En este caso se pasamos el ID de un
layout predefinido en Android (android.R.layout.simple_spinner_item), formado nicamente por un control
TextView, pero podramos pasarle el ID de cualquier layout personalizado del proyecto con cualquier
estructura y conjunto de controles.
Con esto ya se tiene creado el adaptador para los datos a mostrar y slo resta asignar este adaptador al control de
seleccin para que ste muestre los datos en la aplicacin.
Una alternativa a tener en cuenta si los datos a mostrar en el control son estticos sera definir la lista de posibles
valores como un recurso de tipo string-array. Para ello, primero se crea un nuevo archivo XML en la carpeta
/res/values llamado por ejemplo valores_array.xml y se incluyen en l los valores seleccionables de la siguiente
forma:<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="valores_array">
<item>Elem1</item>
<item>Elem2</item>
<item>Elem3</item>
<item>Elem4</item>
<item>Elem5</item>
</string-array>
</resources>
Tras esto, a la hora de crear el adaptador, se utilizara el mtodo createFromResource() para hacer referencia a
este arreglo XML creado:
ArrayAdapter<CharSequence> adaptador =
ArrayAdapter.createFromResource(this,
R.array.valores_array,
android.R.layout.simple_spinner_item);
Control Spinner http://developer.android.com/reference/android/widget/Spinner.html
Las listas desplegables en Android se llaman Spinner. Funcionan de forma similar al de cualquier control de este
tipo, el usuario selecciona la lista, se muestra una especie de lista emergente al usuario con todas las opciones
disponibles y al seleccionarse una de ellas sta queda fijada en el control. Para aadir una lista de este tipo a la
aplicacin se puede utilizar el cdigo siguiente:
43
Manual Mca006
<Spinner android:id="@+id/CmbOpciones"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Las opciones para personalizar el aspecto visual del control (fondo, color y tamao de fuente, ) son las mismas ya
mencionadas para los controles bsicos.
Para enlazar el adaptador (y los datos) a este control se utiliza el siguiente cdigo java:
private Spinner cmbOpciones;
//...
cmbOpciones = (Spinner)findViewById(R.id.CmbOpciones);
adaptador.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
cmbOpciones.setAdapter(adaptador);
Se inicia obteniendo una referencia al control a travs de su ID. Y en la ltima lnea se asigna el adaptador al
control mediante el mtodo setAdapter(). Para personalizar tambin el aspecto de cada elemento en dicha lista
emergente se tiene el mtodo setDropDownViewResource(ID_layout), al que se le puede pasar otro ID de
layout distinto al primero sobre el que se mostrarn los elementos de la lista emergente. En este caso se
hautilizado otro layout predefinido an Android para las listas desplegables
(android.R.layout.simple_spinner_dropdown_item), formado por una etiqueta de texto con la descripcin de
la opcin y un marcador circular a la derecha que indica si la opcin est o no seleccionada (esto ltimo slo para
Android 2.x).
Con estas simples lineas de cdigo se consigue mostrar un control como el mostrado en las siguientes imgenes,
primero para Android 2.x y despus para la versin 4.x:
44
Manual Mca006
Como se puede observar en las imgenes, la representacin del elemento seleccionado (primera imagen) y el de
las opciones disponibles (segunda imagen) es distinto, incluyendo el segundo de ellos incluso algn elemento
grfico a la derecha para mostrar el estado de cada opcin (en este caso, slo para Android 2). Esto es debido a la
utilizacin de dos layouts diferentes para uno y otros elementos.
En cuanto a los eventos disparados por el control Spinner, el ms comnmente utilizado ser el generado al
seleccionarse una opcin de la lista desplegable, onItemSelected. Para capturar este evento se muestra el
siguiente cdigo:
cmbOpciones.setOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent,
android.view.View v, int position, long id) {
lblMensaje.setText("Seleccionado: " + datos[position]);
}
45
Manual Mca006
A diferencia de los ejemplos anteriores, en este evento se definen dos mtodos, el primero de ellos
(onItemSelected) que ser llamado cada vez que se seleccione una opcin en la lista desplegable, y el segundo
(onNothingSelected) que se llamar cuando no haya ninguna opcin seleccionada (esto puede ocurrir por
ejemplo si el adaptador no tiene datos).
A modo de ejemplo, se va a extender el control EditText (cuadro de texto) para mostrar en todo momento el
nmero de caracteres que contiene a medida que se escribe en l..
En la esquina superior derecha del cuadro de texto se va a mostrar el nmero de caracteres del mensaje de texto
introducido, que ira actualizndose a medida se modifica el texto.
Para empezar, se va a crear una nueva clase java heredando del control a utilizar como base, en este
caso EditText.
public class ExtendedEditText extends EditText
{
//...
}
Se sobreescriben los constructores heredados,.
public ExtendedEditText(Context context, AttributeSet attrs, int defStyle){
super(context, attrs,defStyle);
}
46
Manual Mca006
}
escala = getResources().getDisplayMetrics().density;
}
47
Manual Mca006
//...
@Override
public void onDraw(Canvas canvas)
{
//llamada al mtodo base
super.onDraw(canvas);
Para agregar el control a la interfaz de la aplicacin, se incluye en el layout XML de la ventana tal como cualquier
otro control, teniendo en cuenta se debe hacer referencia a l con el nombre completo de la nueva clase creada
(incluido el paquete java)
<ejemplo.gala.android.controlpers1.ExtendedEditText
android:id="@+id/TxtPrueba"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Se observa cmo queda el control en dos dispositivos distintos con densidades de pantalla diferentes.
48
Manual Mca006
Como ejemplo ilustrativo se va a crear un control de identificacin (login) formado por varios controles estndar
de Android. La idea es conseguir un control como el mostrado en la siguiente figura:
A la derecha del botn Login se agrega una etiqueta donde mostrar el resultado de la identificacin del usuario
(login correcto o incorrecto).
A este control se aadirn adems eventos personalizados.
El primer paso es construir la interfaz del control a partir de controles sencillos: etiquetas, cuadros de texto y
botones. Para ello se crea un nuevo layout XML en la carpeta \res\layout con el nombre control_login.xml. En
este archivo se define la estructura del control:
<?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="wrap_content"
android:orientation="vertical"
49
Manual Mca006
android:padding="10dip">
<TextView android:id="@+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/usuario"
android:textStyle="bold" />
<EditText android:id="@+id/TxtUsuario"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:inputType="text" />
<TextView android:id="@+id/TextView02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/contrasena"
android:textStyle="bold" />
<EditText android:id="@+id/TxtPassword"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:inputType="textPassword" />
<LinearLayout android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:layout_width="wrap_content"
50
Manual Mca006
android:layout_height="wrap_content"
android:id="@+id/BtnAceptar"
android:text="@string/login"
android:paddingLeft="20dip"
android:paddingRight="20dip" />
<TextView android:id="@+id/LblMensaje"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dip"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
A continuacin se crea la clase java asociada donde se define toda la funcionalidad del control. Como se utiliz el
LinearLayout para construir el control, esta nueva clase deber heredar tambin de la clase java LinearLayout de
Android. Se deben redefinir los dos constructores bsicos:
ejemplo.gala.android.controlpers2;
//...
51
Manual Mca006
}
}
En el mtodo inicializar() se obtienen las referencias a todos los controles y se asignan los eventos necesarios.
private void inicializar()
{
//Se utiliza el layout 'control_login' como interfaz del control
String infService = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater li =
(LayoutInflater)getContext().getSystemService(infService);
li.inflate(R.layout.control_login, this, true);
// Se obtienen referencias a los distintos control
txtUsuario = (EditText)findViewById(R.id.TxtUsuario);
txtPassword = (EditText)findViewById(R.id.TxtPassword);
btnLogin = (Button)findViewById(R.id.BtnAceptar);
lblMensaje = (TextView)findViewById(R.id.LblMensaje);
//Se asocian los eventos necesarios
asignarEventos();
}
Ms adelante se explicar el mtodos mtodo asignarEventos().
Una vez definida la interfaz y la funcionalidad bsica del nuevo control, se puede utilizar desde otra actividad como
cualquier otro control predefinido. Para ello se hace referencia a l utilizando la ruta completa del paquete java
utilizado, como ejemplo.gala.ControlLogin. Se inserta el nuevo control en la actividad principal de la aplicacin:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sgo="http://schemas.android.com/apk/res/ejemplo.gala.android.controlpers2"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dip" >
<ejemplo.gala.android.controlpers2.ControlLogin
android:id="@+id/CtlLogin"
android:layout_width="match_parent"
52
Manual Mca006
android:layout_height="wrap_content" />
</LinearLayout>
Como se hereda de LinearLayout , se puede utilizar cualquier atributo permitido para dicho tipo de controles, en
este caso se establecen por ejemplo los atributos layout_width, layout_height y background. Si se ejecuta ahora la
aplicacin.
En Android 2.x se tendra algo como lo siguiente:
A continuacin, se aade algo ms de funcionalidad. En primer lugar, se puede aadir algn mtodo pblico
exclusivo del control. Como ejemplo se puede aadir un mtodo que permita modificar el texto de la etiqueta de
resultado del login. Esto no tiene ninguna dificultad:
public void setMensaje(String msg)
{
lblMensaje.setText(msg);
}
53
Manual Mca006
En segundo lugar, todo control debe tener algunos eventos que permitan responder a las acciones del usuario de la
aplicacin. As por ejemplo, los botones tienen un evento OnClick, las listas un evento OnItemSelected, etc. El
control va a disponer de un evento personalizado, llamado OnLogin, disparado cuando el usuario introduce sus
credenciales de identificacin y pulsa el botn Login.
Para definir un evento, se crea una interfaz java para definir el listener. Esta interfaz tan slo tendr un mtodo
llamado onLogin() devolviendo los dos datos introducidos por el usuario (usuario y contrasea):
package ejemplo.gala.android.controlpers2;
54
Manual Mca006
{
btnLogin.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
listener.onLogin(txtUsuario.getText().toString(),
txtPassword.getText().toString());
}
});
}
Ahora la aplicacin principal ya puede implementar el evento OnLogin del control, haciendo por ejemplo la
validacin de las credenciales del usuario y modificando convenientemente el texto de la etiqueta de resultado:
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ctlLogin = (ControlLogin)findViewById(R.id.CtlLogin);
ctlLogin.setOnLoginListener(new OnLoginListener()
{
@Override
public void onLogin(String usuario, String password)
{
//Valida el usuario y la contrasea
if (usuario.equals("demo") && password.equals("demo"))
ctlLogin.setMensaje("Login correcto!");
else
ctlLogin.setMensaje("Vuelva a intentarlo.");
}
});
55
Manual Mca006
}
Al ejecutar ahora la aplicacin principal e introducir las credenciales correctas (por ejemplo para Android 4):
A continuacin se van a definir atributos XML exclusivos para el control. Como ejemplo, se va a definir un atributo
llamado login_text que permita establecer el texto del botn de Login desde el propio layout XML, es decir, en
tiempo de diseo.
Se declara el nuevo atributo y se asocia al control ControlLogin. Esto se realiza en el archivo \res\values\attrs.xml.
Para ello, se aade una nueva seccin <declare-styleable> asociada a ControlLogin dentro del
elemento<resources>, donde se indica el nombre (name) y el tipo (format) del nuevo atributo.
<resources>
<declare-styleable name="ControlLogin">
<attr name="login_text" format="string"/>
</declare-styleable>
</resources>
Para procesar el atributo, se obtiene la lista de atributos asociados a ControlLogin mediante el mtodo
obtainStyledAttributes() del contexto de la aplicacin, se obtiene el valor del nuevo atributo definido (mediante el
ID, que estar formado por la concatenacin del nombre del control y el nombre del atributo, ejemlo
ControlLogin_login_text).
public ControlLogin(Context context, AttributeSet attrs) {
super(context, attrs);
inicializar();
56
Manual Mca006
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sgo="http://schemas.android.com/apk/res/com.gala.android.controlpers2"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dip" >
<com.gala.ControlLogin android:id="@+id/CtlLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
sgo:login_text="Entrar" />
</LinearLayout>
Diseando un control desde cero
Como ejemplo, se va a construir un control permitiendo seleccionar un color entre varios disponibles.
Los colores disponibles van a ser slo cuatro, que se mostrarn en la franja superior del control. En la parte inferior
se mostrar el color seleccionado en cada momento, o permanecer negro si an no se ha seleccionado ningn
color. En Android 2 se mostrara as:
57
Manual Mca006
Los controles creados desde cero , herenda de la clase View (clase padre de la gran mayora de elementos visuales
de Android). En el ejemplo, se redefinen dos eventos de la clase View, onDraw() para el dibujo de la interfaz, y
onMeasure() para el clculo de las dimensiones.
El evento onMeasure()se ejecuta automticamente cada vez que se necesita recalcular el tamao de un control.
Pero, los elementos grficos incluidos en una aplicacin Android se distribuyen por la pantalla de una forma u otra
dependiendo del tipo de contenedor o layout utilizado. Por tanto, el tamao de un control determinado en la
pantalla no depender slo de l, sino de ciertas restricciones impuestas por su elemento contenedor o elemento
padre. Para resolver esto, en el evento onMeasure() se reciben como parmetros las restricciones del elemento
padre en cuanto a ancho y alto del control. Estas restricciones se reciben en forma de objetos MeasureSpec, con
dos campos: modo y tamao. E modo puede contener tres valores posibles:
AT_MOST: indica que el control podr tener como mximo el tamao especificado.
UNSPECIFIED: indica que el control padre no impone ninguna restriccin sobre el tamao.
Dependiendo de esta pareja de datos, se puede calcular el tamao deseado para el control. Para el control de
ejemplo, es utilizar siempre el tamao mximo disponible (o un tamao por defecto de 200*100 en caso de no
recibir ninguna restriccin), por lo que en todos los casos se elegir como tamao del control el tamao recibido
como parmetro:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int ancho = calcularAncho(widthMeasureSpec);
58
Manual Mca006
int alto = calcularAlto(heightMeasureSpec);
setMeasuredDimension(ancho, alto);
}
59
Manual Mca006
}
Como nota importante, al final del evento onMeasure() se debe llamar al mtodo setMeasuredDimension() pasando
como parmetros el ancho y alto calculados para el control.
La interfaz grfica del control se dibuja dentro del evento onDraw(). Este evento recibe como parmetro un objeto
de tipo Canvas
@Override
protected void onDraw(Canvas canvas)
{
//Obtenemos las dimensiones del control
int alto = getMeasuredHeight();
int ancho = getMeasuredWidth();
//Colores Disponibles
Paint pRelleno = new Paint();
pRelleno.setStyle(Style.FILL);
pRelleno.setColor(Color.RED);
canvas.drawRect(0, 0, ancho/4, alto/2, pRelleno);
pRelleno.setColor(Color.GREEN);
canvas.drawRect(ancho/4, 0, 2*(ancho/4), alto/2, pRelleno);
pRelleno.setColor(Color.BLUE);
canvas.drawRect(2*(ancho/4), 0, 3*(ancho/4), alto/2, pRelleno);
pRelleno.setColor(Color.YELLOW);
canvas.drawRect(3*(ancho/4), 0, 4*(ancho/4), alto/2, pRelleno);
//Color Seleccionado
pRelleno.setColor(colorSeleccionado);
canvas.drawRect(0, alto/2, ancho, alto, pRelleno);
//Marco del control
Paint pBorde = new Paint();
pBorde.setStyle(Style.STROKE);
pBorde.setColor(Color.WHITE);
canvas.drawRect(0, 0, ancho-1, alto/2, pBorde);
60
Manual Mca006
canvas.drawRect(0, 0, ancho-1, alto-1, pBorde);
}
El siguiente paso consiste en definir su funcionalidad implementando los eventos a los que debe responder el
control, tanto eventos internos como externos. En este ejemplo slo se van a tener un evento de cada tipo. En
primer lugar se define un evento interno (evento que slo se captura de forma interna al control, sin exponerlo al
usuario) para responder a las pulsaciones del usuario sobre los colores de la zona superior, y se utiliza para
actualizar el color de la zona inferior con el color seleccionado. Para ello se implementa el evento onTouch(),
disparado cada vez que el usuario toca la pantalla sobre el control. Simplemente se consultar las coordenadas
donde ha pulsado el usuario (mediante los mtodos getX() ygetY()), y dependiendo del lugar pulsado se
determinar el color sobre el que se ha seleccionado y se actualizar el valor del atributo colorSeleccionado.
Finalmente, se llama al mtodo invalidate() para refrescar la interfaz del control, reflejando as el cambio en el
color seleccionado, si se ha producido.
@Override
public boolean onTouchEvent(MotionEvent event)
{
//Si se ha pulsado en la zona superior
if (event.getY() > 0 && event.getY() < (getMeasuredHeight()/2))
{
//Si se ha pulsado dentro de los lmites del control
if (event.getX() > 0 && event.getX() < getMeasuredWidth())
{
//Determinamos el color seleccionado segn el punto pulsado
if(event.getX() > (getMeasuredWidth()/4)*3)
colorSeleccionado = Color.YELLOW;
else if(event.getX() > (getMeasuredWidth()/4)*2)
colorSeleccionado = Color.BLUE;
else if(event.getX() > (getMeasuredWidth()/4)*1)
colorSeleccionado = Color.GREEN;
else
colorSeleccionado = Color.RED;
//Refrescamos el control
this.invalidate();
61
Manual Mca006
}
}
return super.onTouchEvent(event);
}
En segundo lugar se crea un evento externo personalizado, disparado cuando el usuario pulsa sobre la zona inferior
del control, como una forma de aceptar definitivamente el color seleccionado. Se llama a este
evento onSelectedColor():
package com.gala.android.controlpers3;
//...
public void setOnColorSelectedListener(OnColorSelectedListener l)
{
listener = l;
}
}
Slo queda disparar el evento en el momento preciso. Esto tambin se realiza dentro del evento onTouch(), cuando
se detecta que el usuario ha pulsado en la zona inferior del:
@Override
public boolean onTouchEvent(MotionEvent event)
{
62
Manual Mca006
//Si se ha pulsado en la zona superior
if (event.getY() > 0 && event.getY() < (getMeasuredHeight()/2))
{
//...
}
//Si se ha pulsado en la zona inferior
else if (event.getY() > (getMeasuredHeight()/2) &&
event.getY() < getMeasuredHeight())
{
//Lanzamos el evento externo de seleccin de color
listener.onColorSelected(colorSeleccionado);
}
return super.onTouchEvent(event);
}
Ahora, la aplicacin principal ya podra suscribirse a este nuevo evento para estar informada cada vez que se
seleccione un color. Sirva la siguiente plantilla a modo de ejemplo:
public class ControlPersonalizado extends Activity
{
private SelectorColor ctlColor;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ctlColor = (SelectorColor)findViewById(R.id.scColor);
ctlColor.setOnColorSelectedListener(new OnColorSelectedListener()
63
Manual Mca006
{
@Override
public void onColorSelected(int color)
{
//Aqu se tratara el color seleccionado (parmetro 'color'
//...
}
});
}
}
64
Manual Mca006
<TabHost android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TabWidget android:layout_width="match_parent"
android:layout_height="wrap_content"
65
Manual Mca006
android:id="@android:id/tabs" />
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@android:id/tabcontent" >
<LinearLayout android:id="@+id/tab1"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView android:id="@+id/textView1"
android:text="Contenido Tab 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout android:id="@+id/tab2"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView android:id="@+id/textView2"
android:text="Contenido Tab 2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
66
Manual Mca006
</LinearLayout>
Se necesita asociar de alguna forma cada pestaa con su contenido, de forma que el el control se comporte
correctamente cuando se cambia de pestaa. Y esto se realiza mediante cdigo en la actividad principal.
Se empieza obteniendo una referencia al control principal TabHost y preparndolo para su configuracin llamando a
su mtodo setup(). Tras esto, se crea un objeto de tipoTabSpec para cada una de las pestaas a aadir mediante
el mtodo newTabSpec(), al que se pasara como parmetro una etiqueta identificativa de la pestaa (ejemplo
mitab1, mitab2, ). Adems, tambin se asignar el layout de contenido correspondiente a la pestaa
llamando al mtodo setContent(), y se indicar el texto y el icono a mostrar en la pestaa mediante el
mtodosetIndicator(texto, icono).
Resources res = getResources();
TabHost tabs=(TabHost)findViewById(android.R.id.tabhost);
tabs.setup();
TabHost.TabSpec spec=tabs.newTabSpec("mitab1");
spec.setContent(R.id.tab1);
spec.setIndicator("",
res.getDrawable(android.R.drawable.ic_btn_speak_now));
tabs.addTab(spec);
spec=tabs.newTabSpec("mitab2");
spec.setContent(R.id.tab2);
spec.setIndicator("TAB2",
res.getDrawable(android.R.drawable.ic_dialog_map));
tabs.addTab(spec);
tabs.setCurrentTab(0);
Si se ejecutamos ahora la aplicacin se tendr algo como lo que muestra la siguiente imagen, donde se puede
cambiar de pestaa y comprobar cmo se muestra correctamente el contenido de la misma.
En Android 2.x
67
Manual Mca006
Y en Android 4.x
En Android 4, el comportamiento por defecto del control TabHost es mostrar slo el texto, o solo el icono, pero no
ambos. Si se eliminamos el texto de la primera pestaa y se vuelve a ejecutar se ver como el icono s aparece.
TabHost.TabSpec spec=tabs.newTabSpec("mitab1");
spec.setContent(R.id.tab1);
spec.setIndicator("",
res.getDrawable(android.R.drawable.ic_btn_speak_now));
tabs.addTab(spec);
Con esta pequea modificacin la aplicacin se vera as en Android 4.x
En cuanto a los eventos disponibles del control TabHost, aunque no suele ser necesario capturarlos, se ve a modo
de ejemplo el ms interesante de ellos, OnTabChanged, que se dispara cada vez que se cambia de pestaa e
informa de la nueva pestaa visualizada. Este evento se puede implementar y asignar mediante el mtodo
setOnTabChangedListener() de la siguiente forma:
tabs.setOnTabChangedListener(new OnTabChangeListener() {
68
Manual Mca006
@Override
public void onTabChanged(String tabId) {
Log.i("AndroidTabsDemo", "Pulsada pestaa: " + tabId);
}
});
En el mtodo onTabChanged() se recibe como parmetro la etiqueta identificativa de la pestaa (no su ID),
asignada cuando se creo el objeto TabSpec correspondiente. Para este ejemplo, lo nico codificado al detectar un
cambio de pestaa ser escribir en el log de la aplicacin un mensaje informativo con la etiqueta de la nueva
pestaa visualizada. As por ejemplo, al cambiar a la segunda pestaa se recibir el mensaje de log: Pulsada
pestaa: mitab2.
LECCION 11 Fragments
Cuando empezaron a aparecer dispositivos de gran tamao tipo tablet, el equipo de Android tuvo que solucionar el
problema de la adaptacin de la interfaz grfica de las aplicaciones a ese nuevo tipo de pantallas. Una interfaz de
usuario diseada para un telfono mvil no se adaptaba fcilmente a una pantalla 4 o 5 pulgadas mayor. La
solucin a esto vino en forma de un nuevo tipo de componente llamado Fragment.
Un fragment no puede considerarse ni un control ni un contenedor, aunque se parecera ms a lo segundo. Un
fragment podra definirse como una porcin de la interfaz de usuario que puede aadirse o eliminarse de una
interfaz de forma independiente al resto de elementos de la actividad, y que por supuesto puede reutilizarse en
otras actividades. Esto, aunque en principio puede parecer algo trivial, va a permitir poder dividir la interfaz en
varias porciones para poder disear diversas configuraciones de pantalla, dependiendo de su tamao y orientacin,
sin tener que duplicar cdigo en ningn momento, sino tan slo utilizando o no los distintos fragmentos para cada
una de las posibles configuraciones.
Comp ejemplo se tiene una aplicacin de correo electrnico, en la que por un lado se debe mostrar la lista de
correos disponibles, con sus campos clsicos De y Asunto, y por otro lado se debe mostrar el contenido completo
del correo seleccionado. En un telfono mvil lo habitual ser tener una primera actividad que muestre el listado de
correos, y cuando el usuario seleccione uno de ellos navegar a una nueva actividad que muestre el contenido de
dicho correo. Sin embargo, en un tablet puede existir espacio suficiente para tener ambas partes de la interfaz en
la misma pantalla, por ejemplo en un tablet en posicin horizontal se podra tener una columna a la izquierda con
el listado de correos y dedicar la zona derecha a mostrar el detalle del correo seleccionado, todo ello sin tener que
cambiar de actividad.
Antes de existir los fragments se podramos haber hecho esto implementando diferentes actividades con diferentes
layouts para cada configuracin de pantalla, pero esto obligara a duplicar gran parte del cdigo en cada actividad.
Tras la aparicin de los fragments, se colocael listado de correos en un fragment y la vista de detalle en otro, cada
uno de ellos acompaado de su lgica de negocio asociada, y tan slo queda definir varios layouts para cada
configuracin de pantalla incluyendo [o no] cada uno de estos fragments.
A modo de aplicacin de ejemplo se va a simular la aplicacin de correo, adaptndola a tres configuraciones
distintas: pantalla normal, pantalla grande horizontal y pantalla grande vertical. Para el primer caso se colocara el
listado de correos en una actividad y el detalle en otra, mientras que para el segundo y el tercero ambos elementos
estarn en la misma actividad, a derecha/izquierda para el caso horizontal, y arriba/abajo en el caso vertical.
Se definen por lo tanto dos fragments: uno para el listado y otro para la vista de detalles. Ambos sern muy
sencillos. Al igual que una actividad, cada fragment se compondr de un archivo de layout XML para la interfaz
(colocado en alguna carpeta /res/layout) y una clase java para la lgica asociada.
69
Manual Mca006
El primero de los fragment a definir contendr tan slo un control ListView, para el que se define un adaptador
personalizado para mostrar dos campos por fila (De y Asunto). El layout XML (se llamara fragment_listado.xml)
quedara por tanto de la siguiente forma:
<?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" >
<ListView
android:id="@+id/LstListado"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Como hemos dicho, todo fragment debe tener asociada, adems del layout, su propia clase java, que en este caso
debe extender de la clase Fragment. Los fragment aparecieron con la versin 3 de Android, por lo que en principio
no estaran disponibles para versiones anteriores. Sin embargo, Google proporcion esta caracterstica tambin
como parte de la librera de compatibillidad android-support, que en versiones recientes del plugin de Android para
Eclipse se aade por defecto a todos los proyectos creados.
Si no fuera as, tambin puede incluirse manualmente en el proyecto mediante la opcin Add Support Library
del men contextual del proyecto.
70
Manual Mca006
71
Manual Mca006
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_listado, container, false);
}
@Override
public void onActivityCreated(Bundle state) {
super.onActivityCreated(state);
lstListado = (ListView)getView().findViewById(R.id.LstListado);
lstListado.setAdapter(new AdaptadorCorreos(this));
}
72
Manual Mca006
La clase Correo es una clase sencilla, que almacena los campos De, Asunto y Texto de un correo.
package com.gala.android.fragments;
public class Correo
{
private String de;
private String asunto;
private String texto;
public Correo(String de, String asunto, String texto){
this.de = de;
this.asunto = asunto;
this.texto = texto;
}
public String getDe(){
return de;
}
public String getAsunto(){
return asunto;
}
public String getTexto(){
return texto;
}
}
En el caso de los fragment los mtodos a sobreescribir son normalmente dos:
onCreateView() y onActivityCreated().
El primero de ellos, onCreateView(), es el equivalente al onCreate() de las actividades, dentro de l es donde
normalmente se asigna un layout determinado al fragment y se prepara con el mtodo inflate() pasndo como
parmetro el ID del layout correspondiente, en este caso caso fragment_listado.
El segundo de los mtodos, onActivityCreated(), se ejecutar cuando la actividad contenedora del fragment est
completamente creada. En este caso, se aprovecha este evento para obtener la referencia al control ListView y
asociarle su adaptador.
73
Manual Mca006
Ahora se define el segundo fragemento, encargado de mostrar la vista de detalle. El layout, llamado
fragment_detalle.xml, slo se compondr de un cuadro de texto:
<?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:background="#FFBBBBBB" >
<TextView
android:id="@+id/TxtDetalle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
La clase java asociada, se limitar a inflar el layout de la interfaz. Adicionalmente se aade un mtodo pblico,
llamado mostrarDetalle(), para asignar el contenido a mostrar en el cuadro de texto.
package com.gala.android.fragments;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
74
Manual Mca006
}
public void mostrarDetalle(String texto) {
TextView txtDetalle =
(TextView)getView().findViewById(R.id.TxtDetalle);
txtDetalle.setText(texto);
}
}
Una vez definidos los dos fragments, solo queda definir las actividades de la aplicacin, con los respectivos layouts
que harn uso de los fragments.
Para la actividad principal se definen 3 layouts diferentes: el primero de ellos para los casos en los que la aplicacin
se ejecute en una pantalla normal (por ejemplo un telfono mvil) y dos para pantallas grandes (uno pensado para
orientacin horizontal y otro para vertical). Todos se llamarn activity_main.xml, y lo que marcar la diferencia
ser la carpeta en donde se colocan cada uno. As, el primero de ellos se colocara en la carpeta por
defecto/res/layout, y los otros dos en las carpetas /res/layout-large (pantalla grande) y/res/latout-largeport (pantalla grande con orientacin vertical) respectivamente. De esta forma, segn el tamao y orientacin de
la pantalla Android utilizar un layout u otro de forma automtica.
Para el caso de pantalla normal, la actividad principal mostrar tan slo el listado de correos, por lo que el layout
incluir tan slo el fragment FragmentListado.
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
class="com.gala.android.fragments.FragmentListado"
android:id="@+id/FrgListado"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Para incluir un fragment en un layout se utiliza una etiqueta <fragment>con un atributo class indicando la ruta
completa de la clase java correspondiente al fragment, en este primer caso
com.gala.android.fragments.FragmentListado..
En este caso de pantalla normal, la vista de detalle se mostrar en una segunda actividad, el layout, se
llama activity_detalle.xml.:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
class="com.gala.android.fragments.FragmentDetalle"
android:id="@+id/FrgDetalle"
75
Manual Mca006
android:layout_width="match_parent"
android:layout_height="match_parent" />
Por su parte, el layout para el caso de pantalla grande horizontal, ser de la siguiente forma:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.gala.android.fragments.FragmentListado"
android:id="@+id/FrgListado"
android:layout_weight="30"
android:layout_width="0px"
android:layout_height="match_parent" />
<fragment class="com.gala.android.fragments.FragmentDetalle"
android:id="@+id/FrgDetalle"
android:layout_weight="70"
android:layout_width="0px"
android:layout_height="match_parent" />
</LinearLayout>
En este caso se incluyen los dos fragment en la misma pantalla, , ambos dentro de un LinearLayout horizontal,
asignando al primero de ellos un peso (propiedad layout_weight) de 30 y al segundo de 70 para que la columna de
listado ocupe un 30% de la pantalla a la izquierda y la de detalle ocupe el resto.
Por ltimo, para el caso de pantalla grande vertical ser practicamente igual, slo que se usa
un LinearLayout vertical.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
76
Manual Mca006
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.gala.android.fragments.FragmentListado"
android:id="@+id/FrgListado"
android:layout_weight="40"
android:layout_width="match_parent"
android:layout_height="0px" />
<fragment class="com.gala.android.fragments.FragmentDetalle"
android:id="@+id/FrgDetalle"
android:layout_weight="60"
android:layout_width="match_parent"
android:layout_height="0px" />
</LinearLayout>
Hecho esto, se podramos ejecutar la aplicacin en el emulador y comprobar si se selecciona automticamente el
layout correcto dependiendo de las caractersticas del AVD utilizado. Por ejemplo si se definen 2 AVD, uno con
pantalla normal y otro grande al que durante las pruebas se modifica su orientacin (pulsando Ctrl+F12). El
resultado es el siguiente:
77
Manual Mca006
78
Manual Mca006
Como se observa en las imgenes anteriores, la interfaz se ha adaptado perfectamente a la pantalla en cada caso,
mostrndose uno o ambos fragments, y en caso de mostrarse ambos distribuyndose horizontal o verticalmente.
LECCION 12 Action Bar: Introduccin, Tabs
Introduccin
La action bar de Android es la barra de ttulo y herramientas que aparece en la parte superior de muchas
aplicaciones actuales. Normalmente muestra un icono, el ttulo de la actividad actual, una serie de botones de
accin, y un men desplegable (men de overflow) donde se incluyen ms acciones que no tienen espacio para
mostrarse como botn o simplemente no se quieren mostrar como tal.
La action bar de Android es uno de esos componentes que Google no ha tratado demasiado bien al no incluirla en
la librera de compatibilidad android-support. Esto significa que de forma nativa tan slo es compatible con
versiones de Android 3.0 o superiores.
Cuando se crea un proyecto con alguna de las ltimas versiones del plugin ADT para Eclipse, la aplicacin creada
por defecto ya incluye de serie su action bar correspondiente. De hecho, si se crea un proyecto nuevo y
directamente se ejecuta sobre un AVD con Android 3.0 o superior no solo se incluye la action bar sino que tambin
aparece una accin Settings como muestra la siguiente imagen.
La action bar de Android toma su contenido de varios sitios diferentes. En primer lugar muestra el icono de la
aplicacin (definido en el AndroidManifest mediante el atributo android:icon del elemento <application>) y
79
Manual Mca006
Tabs
Los action bars pueden ser enlazdos con unas listas de pestaas .El hecho de enlazar una lista de pestaas con la
action bar tiene una serie de ventajas adicionales, relacionadas sobre todo con la adaptacin de tu interfaz a
distintos tamaos y configuraciones de pantalla. As, por ejemplo, si Android detecta que hay suficiente espacio
disponible en la action bar, integrar las pestaas dentro de la propia action bar de forma que no ocupen espacio
extra en la pantalla. Si por el contrario no hubiera espacio suficiente colocara las pestaas bajo la action bar como
de costumbre.
LECCION 13 Mens: Mens y Sub Mens bsicos, Mens contextuales, Opciones Avanzadas
Mens y Sub Mens bsicos
A partir de la versin 3 de Android los mens han caido en desuso debido a la aparicin de la Action Bar. Si se
compila la aplicacin con un target igual o superior a la API 11 (Android 3.0) los mens definidos aparecen, no en
su lugar habitual en la parte inferior de la pantalla, sino en el men desplegable de la action bar en la parte
superior derecha.
En Android existen 3 tipos diferentes de mens:
Mens Principales. Los ms habituales, aparecen en la zona inferior de la pantalla al pulsar el botn
menu del telfono.
Submens. Son mens secundarios que se pueden mostrar al pulsar sobre una opcin de un men
principal.
Mens Contextuales. tiles en muchas ocasiones, aparecen al realizar una pulsacin larga sobre algn
elemento de la pantalla.
Existen dos alternativas a la hora de mostrar un men en una aplicacin Android. La primera de ellas mediante la
definicin del men en un archivo XML, y la segunda creando el men directamente mediante cdigo.
Los archivos XML de men se deben colocar en la carpeta res\menu del proyecto y deben tener una estructura
anloga a la del siguiente ejemplo:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/MnuOpc1" android:title="Opcion1"
android:icon="@android:drawable/ic_menu_preferences"></item>
<item android:id="@+id/MnuOpc2" android:title="Opcion2"
80
Manual Mca006
android:icon="@android:drawable/ic_menu_compass"></item>
<item android:id="@+id/MnuOpc3" android:title="Opcion3"
android:icon="@android:drawable/ic_menu_agenda"></item>
</menu>
La estructura bsica de estos archivos es muy sencilla. Se tiene un elemento principal <menu> conteniendo una
serie de elementos <item> correspondientes con las distintas opciones a mostrar en el men. Estos
elementos <item> tendrn a su vez varias propiedades bsicas, como su ID (android:id), su texto (android:title) o
su icono (android:icon). Los iconos utilizados debern estar en las carpetas res\drawable- del proyecto.
Una vez definido el men en el archivo XML, se tiene que implementar el evento onCreateOptionsMenu() de la
actividad que lo muestra. En este evento se infla el men. Primero se obtiene una referencia al inflater mediante
el mtodo getMenuInflater() y posteriormente se genera la estructura del men llamando a su
mtodo infate() pasndo como parmetro el ID del menu definido en XML, en el ejemplo
ser R.menu.activity_main. Por ltimo se devuelve el valor true para confirmar que debe mostrarse el men.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Alternativa 1
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
A continuacin se mostrara.
Este mismo men tambin se puede crear directamente mediante cdigo, tambin desde el
evento onCreateOptionsMenu(). Para ello, para aadir cada opcin del men se utiliza el mtodo add() sobre el
81
Manual Mca006
objeto de tipo Menu recibido como parmetro del evento. Este mtodo recibe 4 parmetros: ID del grupo asociado
a la opcin (ejemplo Menu.NONE), un ID nico para la opcin (constantes de la clase), el orden de la opcin
(ejemplo Menu.NONE) y el texto de la opcin. Por otra parte, el icono de cada opcin se establece mediante el
mtodo setIcon()pasndole el ID del recurso.
private static final int MNU_OPC1 = 1;
private static final int MNU_OPC2 = 2;
private static final int MNU_OPC3 = 3;
//...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Alternativa 2
menu.add(Menu.NONE, MNU_OPC1, Menu.NONE, "Opcion1")
.setIcon(android.R.drawable.ic_menu_preferences);
menu.add(Menu.NONE, MNU_OPC2, Menu.NONE, "Opcion2")
.setIcon(android.R.drawable.ic_menu_compass);
menu.add(Menu.NONE, MNU_OPC3, Menu.NONE, "Opcion3")
.setIcon(android.R.drawable.ic_menu_agenda);
return true;
}
Construido el men, la implementacin de cada una de las opciones se incluir en el evento
onOptionsItemSelected() de la actividad que mostrar el men. Este evento recibe como parmetro el item de
men que ha sido pulsado por el usuario, cuyo ID se puede recuperar con el mtodo getItemId(). Segn este ID se
puede saber qu opcin ha sido pulsada y ejecutar unas acciones u otras. En el ejemplo, se modificar el texto de
una etiqueta (lblMensaje) colocada en la pantalla principal de la aplicacin.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.MnuOpc1:
lblMensaje.setText("Opcion 1 pulsada!");
return true;
case R.id.MnuOpc2:
lblMensaje.setText("Opcion 2 pulsada!");;
82
Manual Mca006
return true;
case R.id.MnuOpc3:
lblMensaje.setText("Opcion 3 pulsada!");;
return true;
default:
return super.onOptionsItemSelected(item);
}
}
El cdigo anterior sera vlido para el men creado mediante XML. Si se hubiera utilizado la implementacin por
cdigo se tendra que sustituir las constantes R.id.MnuOpc_ por las constantes MNU_OPC_.
Un submen no es ms que un men secundario que se muestra al pulsar una opcin determinada de un men
principal. Los submens en Android se muestran en forma de lista emergente, cuyo ttulo contiene el texto de la
opcin elegida en el men principal. Como ejemplo, se aade un submen a la Opcin 3 del ejemplo anterior,
aadiendo dos nuevas opciones secundarias. Para ello, bastar con insertar en el XML de men un nuevo
elemento <menu> dentro del item correspondiente a la opcin 3. De esta forma, el XML quedara ahora como
sigue:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/MnuOpc1" android:title="Opcion1"
android:icon="@android:drawable/ic_menu_preferences"></item>
<item android:id="@+id/MnuOpc2" android:title="Opcion2"
android:icon="@android:drawable/ic_menu_compass"></item>
<item android:id="@+id/MnuOpc3" android:title="Opcion3"
android:icon="@android:drawable/ic_menu_agenda">
<menu>
<item android:id="@+id/SubMnuOpc1"
android:title="Opcion 3.1" />
<item android:id="@+id/SubMnuOpc2"
android:title="Opcion 3.2" />
</menu>
</item>
</menu>
83
Manual Mca006
Si se vuelve a ejecutar ahora el proyecto y se pulsa la opcin 3 aparecer el correspondiente submen con las dos
nuevas opciones aadidas.:
Para conseguir esto mismo mediante cdigo se procede de forma similar a la anterior, con la nica diferencia de
que la opcin de men 3 se aadir utilizando el mtodo addSubMenu() en lugar de add(), y se guarda una
referencia al submenu. Sobre el submen aadido se insertan las dos nuevas opciones utilizando una vez ms el
mtodo add().:
//Alternativa 2
menu.add(Menu.NONE, MNU_OPC1, Menu.NONE, "Opcion1")
.setIcon(android.R.drawable.ic_menu_preferences);
menu.add(Menu.NONE, MNU_OPC2, Menu.NONE, "Opcion2")
.setIcon(android.R.drawable.ic_menu_compass);
Mens contextuales
Un men contextual siempre va asociado a un control concreto de la pantalla y se muestra al realizar una pulsacin
larga sobre ste. Suele mostrar opciones especficas disponibles nicamente para el elemento pulsado. Por
84
Manual Mca006
ejemplo, en un control de tipo lista se podra tener un men contextual que aparece al pulsar sobre un elemento
concreto de la lista y permite editar su texto o eliminarlo de la coleccin.
A continuacin un ejemplo sencillo. Se parte de un proyecto nuevo, con una etiqueta de texto con el texto Hello
World.
Se va a aadir un men contextual que aparezca al pulsar sobre la etiqueta de texto. Para ello, se debe indicar en
el mtodo onCreate() de la actividad principal que la etiqueta tendr asociado un men contextual. Esto se realiza
con una llamada a registerForContextMenu():
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
</menu>
Por su parte el evento onCreateContextMenu() queda de la siguiente forma:
@Override
85
Manual Mca006
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, v, menuInfo);
switch (item.getItemId()) {
case R.id.CtxLblOpc1:
lblMensaje.setText("Etiqueta: Opcion 1 pulsada!");
return true;
case R.id.CtxLblOpc2:
lblMensaje.setText("Etiqueta: Opcion 2 pulsada!");
return true;
default:
return super.onContextItemSelected(item);
}
}
Con el cdigo anterior, el ejemplo del men contextual se encuentra completado.
Opciones Avanzadas
Los grupos de opciones son un mecanismo que permite agrupar varios elementos de un men para aplicarles
ciertas acciones o asignarles determinadas caractersticas o funcionalidades de forma conjunta. De esta forma, se
puede por ejemplo habilitar o deshabilitar al mismo tiempo un grupo de opciones de men, o hacer que slo se
pueda seleccionar una de ellas.
86
Manual Mca006
Para definir un grupo de opciones mendiante XML basta con colocar dicho grupo dentro de un elemento <group>,
asignando un ID. Se define un men con 3 opciones principales, donde la ltima opcin abre un submen con 2
opciones que formen parte de un grupo. A todas las opciones se le asignaun ID y un texto,.
<men
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/MnuOpc1" android:title="Opcion1"
android:icon="@android:drawable/ic_menu_preferences"></item>
<item android:id="@+id/MnuOpc2" android:title="Opcion2"
android:icon="@android:drawable/ic_menu_compass"></item>
<item android:id="@+id/MnuOpc3" android:title="Opcion3"
android:icon="@android:drawable/ic_menu_agenda">
<menu>
<group android:id="@+id/grupo1">
<item android:id="@+id/SubMnuOpc1"
android:title="Opcion 3.1" />
<item android:id="@+id/SubMnuOpc2"
android:title="Opcion 3.2" />
</group>
</menu>
</item>
</menu>
Las dos opciones del submen se han incluido dentro de un elemento <group>. Esto permitir ejecutar algunas
acciones sobre todas las opciones del grupo de forma conjunta, por ejemplo deshabilitarlas u ocultarlas:
//Deshabilitar todo el grupo
mnu.setGroupEnabled(R.id.grupo1, false);
87
Manual Mca006
exclusiva, tipo RadioButton) o all (seleccin mltiple, tipo CheckBox). En el ejemplo se muestra como hacer
seleccionable slo una de las opciones del grupo:
<group android:id="@+id/grupo1" android:checkableBehavior="single">
<item android:id="@+id/SubMnuOpc1"
android:title="Opcion 3.1" />
<item android:id="@+id/SubMnuOpc2"
android:title="Opcion 3.2" />
</group>
Si se opta por construir el men directamente mediante cdigo se debe utilizar el mtodo
setGroupCheckable() pasando como parmetros el ID del grupo y el tipo de seleccin requerido (exclusivo o no).
private static final int MNU_OPC1 = 1;
private static final int MNU_OPC2 = 2;
private static final int MNU_OPC3 = 3;
private static final int SMNU_OPC1 = 31;
private static final int SMNU_OPC2 = 32;
private static final int GRUPO_MENU_1 = 101;
private int opcionSeleccionada = 0;
//...
88
Manual Mca006
@Override
public boolean onCreateOptionsMenu(Menu menu) {
construirMenu(menu);
return true;
}
Para mantener el estado de las opciones, es necesario en el ejemplo, actualizar el atributo opcionSeleccionada tras
cada pulsacin a una de las opciones..
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
//...
//Omito el resto de opciones por simplicidad
case SMNU_OPC1:
89
Manual Mca006
opcionSeleccionada = 1;
item.setChecked(true);
return true;
case SMNU_OPC2:
opcionSeleccionada = 2;
item.setChecked(true);
return true;
//...
}
}
A continuacin se muestra la prueba del men.
LECCION 14 Widgets
Se mostrar un ejemplo de cmo crear un widget muy bsico, consistente en un simple marco rectangular negro
con un mensaje de texto predeterminado (Mi Primer Widget). El widge a mostar lucir como sigue:
90
Manual Mca006
Los pasos principales para la creacin de un widget Android son los siguientes:
91
Manual Mca006
<TextView android:id="@+id/txtMensaje"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#000000"
android:text="@string/mi_primer_widget" />
</FrameLayout>
</FrameLayout>
El layout de los widgets de Android est basado en un tipo especial de componentes llamados RemoteViews, no es
posible utilizar en su interfaz todos los contenedores y controles disponibles sino slo unos pocos bsicos que se
indican a continuacin:
Como segundo paso del proceso de construccin se crea un nuevo archivo XML donde se define un conjunto de
propiedades del widget, como por ejemplo su tamao en pantalla o su frecuencia de actualizacin. Este XML se
deber crear en la carpeta \res\xml del proyecto. En este ejemplo se llamar miwidget_wprovider.xml y tendr la
siguiente estructura:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/miwidget"
android:minWidth="110dip"
1
android:minHeight="40dip"
android:label="@string/mi_primer_widget"
android:updatePeriodMillis="3600000"
/>
Para el widget se estan definiendo las siguientes propiedades:
92
Manual Mca006
Existen varias propiedades ms que se pueden definir, por ejemplo el icono de vista previa del widget
(android:previewImage, slo para Android >3.0) o el indicativo de si el widget ser redimensionable
(android:resizeMode, slo para Android >3.1) o la actividad de configuracin del widget (android:configure).
.
La pantalla inicial de Android se divide en un mnimo de 44 celdas (segn el dispositivo pueden ser ms) donde
se pueden colocar aplicaciones, accesos directos y widgets. Teniendo en cuenta las diferentes dimensiones de estas
celdas segn el dispositivo y la orientacin de la pantalla, existe una frmula sencilla para ajustar las dimensiones
del widget para que ocupe un nmero determinado de celdas sea cual sea la orientacin:
El tercer paso consiste en implementar la funcionalidad del widget en su clase java asociada. Esta clase deber
heredar de AppWidgetProvider, que a su vez no es ms que una clase auxiliar derivada de BroadcastReceiver, ya
que los widgets de Android no son ms que un caso particular de este tipo de componentes.
En esta clase se debe implementar los mensajes a los que se va a responder desde el widget, entre los que
destacan:
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
93
Manual Mca006
@Override
public void onUpdate(Context context,
AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
//Actualizar el widget
//...
}
}
El ltimo paso del proceso ser declarar el widget dentro del manifest de la aplicacin. Para ello, se edita el
archivo AndroidManifest.xml para incluir la siguiente declaracin dentro del elemento <application>:
<application>
...
<receiver android:name=".MiWidget" android:label="Mi Primer Widget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/miwidget_wprovider" />
</receiver>
</application>
El widget se declarar como un elemento <receiver> y se debe aportar la siguiente informacin:
Atributo name: Referencia a la clase java del widget, creada en el paso anterior.
Elemento <intent-filter>, donde se indican los eventos a los que responder el widget, normalmente se aade el
evento APPWIDGET_UPDATE, para detectar la accin de actualizacin.
Elemento <meta-data>, donde se hace referencia con su atributo resource al XML de configuracin.
Para probar el widget, se puede ejecutar el proyecto de Eclipse en el emulador de Android, esperar a que se
ejecute la aplicacin principal (que estar vaca, porque no se ha incluido ninguna funcionalidad para ella), ir a la
pantalla principal del emulador y aadir el widget al escritorio tal cmo se hara en un dispositivo fsico.
LECCION 15 Preferencias: SharedPreferences, PreferenceActivity
Shared Preferences
Las preferencias no son ms que datos que una aplicacin debe guardar para personalizar la experiencia del
usuario, por ejemplo informacin personal, opciones de presentacin, etc. Las preferencias de una aplicacin se
94
Manual Mca006
podran almacenar en una Base de Datos, y no tendra nada de malo, pero Android proporciona otro mtodo
alternativo diseado especficamente para administrar este tipo de datos: las preferencias compartidas o shared
preferences. Cada preferencia se almacenar en forma de clave-valor, es decir, cada una de ellas estar
compuesta por un identificador nico (p.e. email) y un valor asociado a dicho identificador (p.e.
prueba@email.com). Estos datos se almacenan en documentos XML.
La API para el manejo de estas preferencias es muy sencilla. Toda la gestin se centraliza en la clase
SharedPrefences, que representar a una coleccin de preferencias. Una aplicacin Android puede gestionar varias
colecciones de preferencias, que se diferenciarn mediante un identificador nico. Para obtener una referencia a
una coleccin determinada utilizaremos el mtodo getSharedPrefences() al que se pasa el identificador de la
coleccin y un modo de acceso. El modo de acceso indicar qu aplicaciones tendrn acceso a la coleccin de
preferencias y qu operaciones tendrn permitido realizar sobre ellas. Android ofrece tres posibilidades:
MODE_PRIVATE. Slo la aplicacin tiene acceso a estas preferencias.
MODE_WORLD_READABLE. Todas las aplicaciones pueden leer estas preferencias, pero slo la aplicacin puede
modificarlas.
MODE_WORLD_WRITABLE. Todas las aplicaciones pueden leer y modificar estas preferencias.
Para obtener una referencia a una coleccin de preferencias llamada por ejemplo MisPreferencias y como modo
de acceso exclusivo para la aplicacin se hara lo siguiente:
SharedPreferences prefs =
getSharedPreferences("MisPreferencias",Context.MODE_PRIVATE);
Una vez obtenida una referencia a la coleccin de preferencias, ya es posible obtener, insertar o modificar
preferencias utilizando los mtodos get o put correspondientes al tipo de dato de cada preferencia. As, por
ejemplo, para obtener el valor de una preferencia llamada email de tipo String:
SharedPreferences prefs =
getSharedPreferences("MisPreferencias",Context.MODE_PRIVATE);
String correo = prefs.getString("email", "por_defecto@email.com");
Al mtodo getString() se le pasa el nombre de la preferencia a recuperar y un segundo parmetro con un valor por
defecto. Este valor por defecto ser el devuelto por el mtodo getString() si la preferencia solicitada no existe en la
coleccin. Adems del mtodo getString(), existen mtodos anlogos para el resto de tipos de datos bsicos, por
ejemplo getInt(), getLong(), getFloat(), getBoolean(),
Para actualizar o insertar nuevas preferencias el proceso ser igual de sencillo, con la nica diferencia de que la
actualizacin o insercin no se hace directamente sobre el objeto SharedPreferences, sino sobre su objeto de
edicin SharedPreferences.Editor. A este ltimo objeto se accede mediante el mtodo edit() de la clase
SharedPreferences. Una vez obtenida la referencia al editor, se utilizan los mtodos put correspondientes al tipo de
datos de cada preferencia para actualizar/insertar su valor, por ejemplo putString(clave, valor), para actualizar una
preferencia de tipo String. De forma anloga a los mtodos get, se tienen disponibles mtodos put para todos los
tipos de datos bsicos: putInt(), putFloat(), putBoolean(), etc. Finalmente, una vez actualizados/insertados todos
los datos necesarios se llama al mtodo commit() para confirmar los cambios. A continuacin se muestra un
ejemplo sencillo:
SharedPreferences prefs =
getSharedPreferences("MisPreferencias",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("email", "modificado@email.com");
95
Manual Mca006
editor.putString("nombre", "Prueba");
editor.commit();
Las preferencias se almacenan en una ruta con el siguiente patrn:
/data/data/paquetejava/shared_prefs/nombre_coleccion.xml
Si se descarga este archivo y se abrimos con cualquier editor de texto se visualiza un contenido como el siguiente:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="nombre">prueba</string>
<string name="email">modificado@email.com</string>
</map>
Preference Activity
Android ofrece una forma alternativa de definir mediante XML un conjunto de opciones para una aplicacin y crear
las pantallas necesarias para permitir al usuario modificarlas a su gusto.
Si se revisa en cualquier pantalla de preferencias estandar de Android se observa que todas comparten una interfaz
comun, similar por ejemplo a la que se muestra en la imagen siguiente (correpondiente a la pantalla de opciones
de la galera de imgenes de Android).
Si se observa la imagen anterior se ve cmo las diferentes opciones se organizan dentro de la pantalla de
opciones en varias categoras (General Settings y Slideshow Settings). Dentro de cada categora pueden
aparecer varias opciones de diversos tipos, como por ejemplo de tipo checkbox (Confirm deletions) o de tipo lista
de seleccin (Display size). pantalla de opciones, categoras, y tipos de opcin son los tres elementos
principales con los que se definen el conjunto de opciones o preferencias de la aplicacin.
96
Manual Mca006
La pantalla de opciones se define mediante un XML, de forma similar a como se define cualquier layout, aunque en
este caso se debe colocar en la carpeta /res/xml. El contenedor principal de la pantalla de preferencias ser el
elemento <PreferenceScreen>. Este elemento representar a la pantalla de opciones en s, dentro de la cual se
incluyen el resto de elementos. Dentro de ste se puede incluir la lista de opciones organizadas por categoras, que
se representar mediante el elemento<PreferenceCategory> al que se da un texto descriptivo utilizando su
atributo android:title. Dentro de cada categora se puede aadir cualquier nmero de opciones, las cuales pueden
ser de distintos tipos, entre los que destacan:
CheckBoxPreference. Marca seleccionable.
EditTextPreference. Cadena simple de texto.
ListPreference. Lista de valores seleccionables (exclusiva).
MultiSelectListPreference. Lista de valores seleccionables (mltiple).
Cada uno de estos tipos de preferencia requiere la definicin de diferentes atributos
CheckBoxPreference
Representa un tipo de opcin que slo puede tomar dos valores distintos: activada o desactivada. Es el equivalente
a un control de tipo checkbox. En este caso tan slo se tiene que especificar los atributos: nombre interno de la
opcin (android:key), texto a mostrar (android:title) y descripcin de la opcin (android:summary). Por ejemplo:
<CheckBoxPreference
android:key="opcion1"
android:title="Preferencia 1"
android:summary="Descripcin de la preferencia 1" />
EditTextPreference
Representa un tipo de opcin que puede contener como valor una cadena de texto. Al pulsar sobre una opcin de
este tipo se mostrar un cuadro de dilogo sencillo que solicitar al usuario el texto a almacenar. Para este tipo,
adems de los tres atributos comunes a todas las opciones (key, title y summary) tambin se tiene que indicar el
texto a mostrar en el cuadro de dilogo, mediante el atributo android:dialogTitle. Un ejemplo sera el siguiente:
<EditTextPreference
android:key="opcion2"
android:title="Preferencia 2"
android:summary="Descripcin de la preferencia 2"
android:dialogTitle="Introduce valor" />
ListPreference
Representa un tipo de opcin que puede tomar como valor un elemento, y slo uno, seleccionado por el usuario
entre una lista de valores predefinida. Al pulsar sobre una opcin de este tipo se mostrar la lista de valores
posibles y el usuario podr seleccionar uno de ellos.. Adems de los cuatro ya comentados
(key, title, summary y dialogTitle) se tienen que aadir dos ms, uno de ellos indicando la lista de valores a
visualizar en la lista y el otro indicando los valores internos a utilizar para cada uno de los valores de la lista
97
Manual Mca006
anterior (Ejemplo: al usuario se puede mostrar una lista con los valores Espaol y Francs, pero internamente
almacenarlos como ESP y FRA).
Estas listas de valores se defininen tambin como archivos XML dentro de la carpeta/res/xml. Se definen para ello
los recursos de tipos <string-array> necesarios, en este caso dos, uno para la lista de valores visibles y otro para
la lista de valores internos, cada uno de ellos con su ID nico correspondiente. El archivo, por ejemplo se llama
codigospaises.xml:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<string-array name="pais">
<item>Espaa</item>
<item>Francia</item>
<item>Alemania</item>
</string-array>
<string-array name="codigopais">
<item>ESP</item>
<item>FRA</item>
<item>ALE</item>
</string-array>
</resources>
En la preferencia se utilizan los atributos android:entries y android:entryValues para hacer referencia a estas listas:
<ListPreference
android:key="opcion3"
android:title="Preferencia 3"
android:summary="Descripcin de la preferencia 3"
android:dialogTitle="Indicar Pais"
android:entries="@array/pais"
android:entryValues="@array/codigopais" />
MultiSelectListPreference
[A partir de Android 3.0.x / Honeycomb] Las opciones de este tipo son muy similares a las ListPreference, con la
diferencia de que el usuario puede seleccionar varias de las opciones de la lista de posibles valores. Los atributos a
asignar son por tanto los mismos que para el tipo anterior.
<MultiSelectListPreference
98
Manual Mca006
android:key="opcion4"
android:title="Preferencia 4"
android:summary="Descripcin de la preferencia 4"
android:dialogTitle="Indicar Pais"
android:entries="@array/pais"
android:entryValues="@array/codigopais" />
Como ejemplo completo, se muestra como queda definida una pantalla de opciones con las 3 primeras opciones
comentadas, divididas en 2 categoras llamadas por simplicidad Categora 1 y Categora 2. El archivo se llama
opciones.xml.
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Categora 1">
<CheckBoxPreference
android:key="opcion1"
android:title="Preferencia 1"
android:summary="Descripcin de la preferencia 1" />
<EditTextPreference
android:key="opcion2"
android:title="Preferencia 2"
android:summary="Descripcin de la preferencia 2"
android:dialogTitle="Introduce valor" />
</PreferenceCategory>
<PreferenceCategory android:title="Categora 2">
<ListPreference
android:key="opcion3"
android:title="Preferencia 3"
android:summary="Descripcin de la preferencia 3"
android:dialogTitle="Indicar Pais"
android:entries="@array/pais"
android:entryValues="@array/codigopais" />
99
Manual Mca006
</PreferenceCategory>
</PreferenceScreen>
Ya se tiene definida la estructura de la pantalla de opciones, pero an queda un paso ms para poder hacer uso de
ella desde la aplicacin. Adems de la definicin XML de la lista de opciones, se debe implementar una nueva
actividad, que ser a la que se hace referencia cuando se quiere mostrar en la pantalla de opciones y la que se
encargar internamente de gestionar todas las opciones, guardarlas, modificarlas, etc, a partir de la definicin XML.
Android facilita las cosas ofrecindo la clase PreferenceActivity. Tan slo se debe crear una nueva actividad que
extienda a esta clase e implementar su evento onCreate() para aadir una llamada al
mtodo addPreferencesFromResource(), donde se indica el archivo XML conteniendo la pantalla de opciones.
public class PantallaOpciones extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.opciones);
}
}
Se debe agregar esta actividad al archivo AndroidManifest.xml, al igual que cualquier otra actividad utilizada en la
aplicacin.
<activity android:name=".PantallaOpciones"
android:label="@string/app_name">
</activity>
Solo resta aadir a la aplicacin algn mecanismo para mostrar la pantalla de preferencias. Esta opcin suele estar
en un men, pero por simplificar el ejemplo se va a aadir simplemente un botn (btnPreferencias) que llame a la
ventana de preferencias.
Al pulsar este botn se llama a la ventana de preferencias mediante el mtodo startActivity(),
btnPreferencias = (Button)findViewById(R.id.BtnPreferencias);
btnPreferencias.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(AndroidPrefScreensActivity.this,
PantallaOpciones.class));
100
Manual Mca006
}
});
Al ejecutar la aplicacin en el emulador y pulsar el botn de preferencias para mostrar la nueva pantalla de
opciones. Debe quedar como muestra la imagen siguiente:
La primera opcin se puede marcar o desmarcar directamente pulsando sobre la check de su derecha. La segunda,
de tipo texto, mostrar al pulsarla un pequeo formulario para solicitar el valor de la opcin.
Por ltimo, la opcin 3 de tipo lista, mostrar una ventana emergente con la lista de valores posibles, donde se
puede seleccionar slo uno de ellos.
101
Manual Mca006
102
Manual Mca006
103
Manual Mca006
LocationManager.GPS_PROVIDER. Localizacin por GPS.
De esta forma, si se requiere saber si el GPS est habilitado o no en el dispositivo (y actuar en consecuencia), se
escribira el siguiente cdigo:
//Si el GPS no est habilitado
if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
mostrarAvisoGpsDeshabilitado();
}
En el cdigo anterior, se verifica si el GPS est activado y en caso negativo se muestra al usuario un mensaje de
advertencia.
LECCION 17 Mapas : Comparacin v1 y v2, Introduccin v2, Objeto Google Map, Mtodos
La v1 de Google Maps, se encuentra obsoleta.
A finales de 2012 Google presenta la segunda versin de su API de Google Maps para Android. Esta nueva versin
presenta muchas novedades interesantes, de las que cabe destacar las siguientes:
Integracin con los Servicios de Google Play (Google Play Services) y la Consola de APIs.
Utilizacin a travs de un nuevo tipo especfico de fragment (MapFragment), una mejora muy esperada por
muchos.
Utilizacin de mapas vectoriales, lo que repercute en una mayor velocidad de carga y una mayor eficiencia en
cuanto a uso de ancho de banda.
Mejoras en el sistema de cach, lo que reducir en gran medida las famosas reas en blanco que tardan en cargar.
Los mapas son ahora 3D, es decir, moviendo el punto de vista de forma que se ve en perspectiva.
Al margen de las novedades generales, como desarrolladores qu diferencias se encuentran con respecto a la API
anterior a la hora de desarrollar aplicaciones Android?
Pues la principal ser el componente a utilizar para la inclusin de mapas en la aplicacin.En la anterior versin de
la API, para incluir un mapa en la aplicacin se debautilizar un control de tipo MapView, que adems requera que
su actividad contenedora fuera del tipo MapActivity. Con la nueva API no se utilizan estos dos componentes y solo
se utiliza un nuevo tipo especfico de fragment llamado MapFragment. Esto permitir entre otras cosas aadir uno
[o varios, esto tambin es una novedad] mapas a cualquier actividad, sea del tipo que sea, y contando por
supuesto con todas las ventajas del uso de fragments. .
En primer lugar, dado que la API v2 se proporciona como parte del SDK de Google Play Services, ser necesario
incorporar previamente al entorno de desarrollo dicho paquete. Desde Eclipse usar Android SDK Manager y
descargar del apartado de extras el paquete llamado Google Play Services.
104
Manual Mca006
Tras pulsar el botn de Install y aceptar la licencia correspondiente el paquete quedar instalado en el sistema,
concretamente en la ruta: <carpeta-sdk-android>/extras/google/google_play_services/. .
El siguiente paso ser obtener una API Key para poder utilizar el servicio de mapas de Google en la aplicacin. La
nueva API de mapas de Android se ha integrado por fin en la Consola de APIs de Google por lo que el primer paso
ser acceder a ella. Una vez accedido, se tiene que crear un nuevo proyecto desplegando el men superior
izquierdo y seleccionando la opcin Create.
Aparecer entonces una ventana que solicitar el nombre del proyecto. Se introduce algn nombre descriptivo y se
acepta.
105
Manual Mca006
Una vez creado el proyecto, se accede a la opcin Services del men izquierdo. Desde esta ventana se puede
activar o desactivar cada uno de los servicios de Google a utilizar. En este caso slo se activar el servicio llamado
Google Maps Android API v2 pulsando sobre el botn ON/OFF situado justo a su derecha.
Una vez activado aparecer una nueva opcin en el men izquierdo llamada API Access. Accediendo a dicha
opcin se tiene la posibilidad de obtener la nueva API Key que permita utilizar el servicio de mapas desde una
aplicacin particular.
Para ello, se pulsa el botn Create new Android key. Esto llevar a un cuadro de dilogo donde se introducen
algunos datos identificativos de la aplicacin. En concreto se necesitab dos: la huella digital (SHA1) del certificado
con el que se firma la aplicacin, y el paquete java utilizado.. Toda aplicacin Android debe ir firmada para poder
ejecutarse en un dispositivo, tanto fsico como emulado. Este proceso de firma es uno de los pasos a hacer siempre
106
Manual Mca006
antes de distribuir pblicamente una aplicacin. Adicionalmentes, durante el desarrollo de la misma, para realizar
pruebas y la depuracin del cdigo, tambin se firma la aplicacin con un certificado de pruebas. Se puede saber
en qu carpeta del sistema est almacenado este certificado accediendo desde Eclipse al men Window
/Preferences y accediendo a la seccin Android / Build.
Para crear un proyecto de mapas, se abre un nuevo proyecto estandar de Android, ejeplo android-mapas-api2.
Lo primero a hacer ser aadir al archivo AndroidManifest.xml con la API Key generado. Para ello se aade al
archivo, dentro de la etiqueta <application>, un nuevo elemento <meta-data> con los siguientes datos:
...
<application>
...
<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="api_key"/>
...
</application>
Como valor del parmetro android:value se tiene que poner un API Key generada.
Siguiendo con el AndroidManifest, tambin se tiene que incluir una serie de permisos que permitan hacer uso de
los mapas. En primer lugar se debe definir y utilizar un permiso llamado
tu.paquete.java.permission.MAPS_RECEIVE,:
<permission
android:name="com.gala.android.mapasapi2.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.gala.android.mapasapi2.
permission.MAPS_RECEIVE"/>
Adems, se tienen que aadir permisos adicionales que permitan acceder a los servicios web de Google, a Internet,
y al almacenamiento externo del dispositivo (utilizado para la cach de los mapas):
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.
permission.READ_GSERVICES"/>
107
Manual Mca006
Por ltimo, como la API v2 de Google Maps Android utiliza OpenGL ES versin 2, se debe especificar tambin dicho
requisito en el AndroidManifest aadiendo un nuevo elemento <uses-feature>:
<uses-feature android:glEsVersion="0x00020000"
android:required="true"/>
Una vez configurado todo lo necesario en el AndroidManifest, y antes de escribir el cdigo, se tienen que seguir
aadiendo elementos externos al proyecto. El primero de ellos ser referenciar desde el proyecto la librera con el
SDK de Google Play Services. Para ello, desde Eclipse se puede importar la librera al conjunto de proyectos
mediante la opcin de men File / Import / Existing Android Code Into Workspace. Este paquete se localiza en
la ruta <carpeta-sdk-android>/extras/google/google_play_services/libproject/google-play-services_lib.
Tras seleccionar la ruta correcta se deja el resto de opciones con sus valores por defecto y se pulsa Finish para
que Eclipse importe esta librera al conjunto de proyectos.
El siguiente paso ser referenciar esta librera desde el proyecto de ejemplo. Para ello se va a sus propiedades
pulsando botn derecho / Properties sobre el proyecto y accediendo a la seccin Android de las preferencias. En
dicha ventana se puede aadir una nueva librera en la seccin inferior llamada Library. Cuando se pulsa el botn
Add aparecer la librera recien importada y se puede seleccionar directamente, aadindose a la lista de
libreras referenciadas por el proyecto.
108
Manual Mca006
Como ltimo paso de configuracin del proyecto, si se requiere que la aplicacin se pueda ejecutar desde versiones
antiguas de Android (concretamente desde la versin de Android 2.2) se debe asegurar que el proyecto incluye la
librera android-support-v4.jar, que debera aparecer si se despliega la seccin Android Dependencies o la carpeta
lib del proyecto.
Las versiones ms recientes de ADT incluyen por defecto esta librera en los proyectos, pero si no est incluida se
puede hacer mediante la opcin del men contextual Android Tools / Add Support Library sobre el proyecto, o
bien de forma manual.
109
Manual Mca006
Para trabajar con los mapas simplemente se aade el control correspondiente al layout de la actividad principal. En
el caso de la nueva API v2 este control se aadir en forma de fragment de un determinado tipo (concretamente
de la nueva clase com.google.android.gms.maps.SupportMapFragment), quedando por ejemplo de la siguiente
forma:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment"/>
Por supuesto, como se utiliza fragments, la actividad principal tambin tendr que extender a FragmentActivity. Se
Usa tambin la versin de FragmentActivity incluida en la librera android-supportpara ser compatibles con la
mayora de las versiones Android actuales.
public class MainActivity extends android.support.v4.app.FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
...
}
Con esto, ya se puede ejecutar y probar la aplicacin.
110
Manual Mca006
111
Manual Mca006
toast1.show();
}
});
Si se ejecuta esta sencilla aplicacin en el emulador y se pulsa el botn se ve como en la parte inferior de la
pantalla aparece el mensaje Toast por defecto, que tras varios segundos desaparecer automticamente.
Este es el comportamiento por defecto de las notificaciones toast, sin embargo tambin se puede personalizar un
poco cambiando la posicin en la pantalla. Para esto se utiliza el mtodo setGravity(), donde se indica en qu zona
se desea aparezca la notificacin. La zona se indica con alguna de las constantes definidas en la
clase Gravity: CENTER, LEFT, BOTTOM, o con alguna combinacin de stas.
En el ejemplo se coloca la notificacin en la zona central izquierda de la pantalla. Para ello, se aade un segundo
botn a la aplicacin de ejemplo que muestre un toast con estas caractersticas:
btnGravity.setOnClickListener(new OnClickListener() {
112
Manual Mca006
@Override
public void onClick(View arg0) {
Toast toast2 =
Toast.makeText(getApplicationContext(),
"Toast con gravity", Toast.LENGTH_SHORT);
toast2.setGravity(Gravity.CENTER|Gravity.LEFT,0,0);
toast2.show();
}
});
Si se vuelve a ejecutar la aplicacin y se pulsa el nuevo botn se ve como el toast aparece en la zona indicada de
la pantalla:
Si esto no es suficiente y se necesita personalizar por completo el aspecto de la notificacin, Android ofrece la
posibilidad de definir un layout XML propio para toast, donde se puede incluir todos los elementos necesarios para
adaptar la notificacin a las necesidades requeridas. para el ejemplo se define un layout sencillo, con una imagen y
una etiqueta de texto sobre un rectngulo gris:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
113
Manual Mca006
android:id="@+id/lytLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:background="#555555"
android:padding="5dip" >
<ImageView android:id="@+id/imgIcono"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/marcador" />
<TextView android:id="@+id/txtMensaje"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="#FFFFFF"
android:paddingLeft="10dip" />
</LinearLayout>
Se guarda este layout con el nombre toast_layout.xml, y se colocaen la carpeta res/layout del proyecto.
A continuacin se muestra el cdigo con un tercer botn:
btnLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast toast3 = new Toast(getApplicationContext());
114
Manual Mca006
TextView txtMsg = (TextView)layout.findViewById(R.id.txtMensaje);
txtMsg.setText("Toast Personalizado");
toast3.setDuration(Toast.LENGTH_SHORT);
toast3.setView(layout);
toast3.show();
}
});
Si se ejecuta ahora la aplicacin de ejemplo y se pulsa el nuevo botn, el toast aparece con la estructura definida
en el layout personalizado.
Barras de Estado
Existe otro tipo de notificaciones algo ms persistentes, las notificaciones de la barra de estado de Android. Estas
notificaciones son las que se muestran en el dispositivo cuando se recibes un mensaje SMS, cuando se tienen
actualizaciones disponibles, cuando se tiene el reproductor de msica abierto en segundo plano, Estas
notificaciones constan de un icono y un texto mostrado en la barra de estado superior, y adicionalmente un
mensaje algo ms descriptivo y una marca de fecha/hora que se puede consultar desplegando la bandeja del
sistema. A modo de ejemplo, cuando se tiene una llamada perdida en el terminal, se muestra por un lado un icono
en la barra de estado
115
Manual Mca006
y un mensaje con ms informacin al desplegar la bandeja del sistema, donde en este caso concreto se informa
del evento que se ha producido (Missed call), el nmero de telfono asociado, y la fecha/hora del evento.
Adems, al pulsar sobre la notificacin se dirige automticamente al historial de llamadas.
Se crea como ejemplo un nico botn que genere una notificacin de ejemplo en la barra de estado, con todos los
elementos comentados y con la posibilidad de dirigirse a la propia aplicacin de ejemplo cuando se pulse sobre ella.
Para generar notificaciones en la barra de estado del sistema, lo primero que se debe hacer es obtener una
referencia al servicio de notificaciones de Android, a travs de la clase NotificationManager. Se utiliza para ello el
mtodo getSystemService() indicando como parmetro el identificador del servicio correspondiente, en este caso
Context.NOTIFICATION_SERVICE.
//Obtenemos una referencia al servicio de notificaciones
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager notManager =
(NotificationManager) getSystemService(ns);
Seguidamente se configuran las caractersticas de la notificacin. En primer lugar se establece el icono y el texto a
mostrar en la barra de estado, y se registra la fecha/hora asociada a la notificacin. Con estos datos se construye
un objeto Notification. En el ejemplo, se utiliza un icono predefinido de Android, el mensaje de ejemplo Alerta!, y
se registra la fecha/hora actual, devuelta por el mtodo System.currentTimeMillis():
//Configuramos la notificacin
int icono = android.R.drawable.stat_sys_warning;
CharSequence textoEstado = "Alerta!";
long hora = System.currentTimeMillis();
Notification notif =
new Notification(icono, textoEstado, hora);
El segundo paso ser utilizar el mtodo setLatestEventInfo() para asociar a la notificacin la informacin a mostrar
al desplegar la bandeja del sistema (ttulo y descripcin) e indicar la actividad a la cual se debe dirigir al usuario
116
Manual Mca006
automticamente si ste pulsa sobre la notificacin. Los dos primeros datos son simples cadenas de texto, pero
cmo se indica la aplicacin a ejecutar si se pulsa sobre la notificacin?
Para esto ltimo se debe construir un objeto PendingIntent, que ser el que contenga la informacin de la actividad
asociada a la notificacin y que ser lanzado al pulsar sobre ella. Para ello se define en primer lugar un
objeto Intent, indicando la clase de la actividad concreta a lanzar, en el ejemplo ser la propia actividad principal
(AndroidNotificacionesActivity.class). Este intent se utiliza para construir elPendingIntent final mediante el
mtodo PendingIntent.getActivity().
//Configuramos el Intent
Context contexto = getApplicationContext();
CharSequence titulo = "Mensaje de Alerta";
CharSequence descripcion = "Ejemplo de notificacin.";
notif.setLatestEventInfo(
contexto, titulo, descripcion, contIntent);
Como opciones adicionales, tambin se puede indicar por ejemplo que la notificacin desaparezca automticamente
de la bandeja del sistema cuando se pulsa sobre ella. Esto se hace aadiendo al atributo flags de la notificacin el
valor Notification.FLAG_AUTO_CANCEL.
Tambin se puede indicar que al generarse la notificacin el dispositivo debe emitir un sonido, vibrar o encender el
LED de estado presente en muchos terminales. Esto se conseguiramos aadiendo al atributo defaults de la
notificacin los valoresDEFAULT_SOUND, DEFAULT_VIBRATE o DEFAULT_LIGHTS.
//AutoCancel: cuando se pulsa la notificain sta desaparece
notif.flags |= Notification.FLAG_AUTO_CANCEL;
117
Manual Mca006
//notif.defaults |= Notification.DEFAULT_LIGHTS;
Existen otras muchas opciones y personalizaciones de stas ltimas, que se pueden consultar en la documentacin
oficial de la clase Notification de Android (atributos flags y defaults).
Por ltimo, una vez configuradas las opciones de la notificacin se puede generar llamando al mtodo notify(),
pasando como parmetro un identificador nico definido y el objeto Notification construido.
//Enviar notificacin
notManager.notify(NOTIF_ALERTA_ID, notif);
Ya es posible probar el ejemplo..
Si se sale de la aplicacin y se despliega la bandeja del sistema se puede verificar el resto de informacin de la
notificacin tal como muestra la siguiente imagen:
118
Manual Mca006
Por ltimo, si se pulsa sobre la notificacin se debera abrir de nuevo automticamente la aplicacin de ejemplo.
119