Sunteți pe pagina 1din 119

Manual Mca006

S diferente, intgrate

Mca006

Manual Mca006 CURSO ANDROID DESARROLLO


de APLICACIONES MVILES, 24 horas

Autor: Olrando Gutirrez


Fecha: 10 / 05 / 2013

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Leccin 2 Estructura de un proyecto Android

Pag. 17

Leccin 3 Componentes de una aplicacin Android

Pag. 18

Leccin 4 Desarrollando la primera aplicacin en Android

Pag. 23

Leccin 5 Layouts: Frame, Linear, Table, Grid , Relative

Pag. 31

Leccin 6 Controles: Propiedades, Eventos, Personalizacin

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

Leccin 10 Pestaas (Tabs)

Pag. 69

Leccin 11 Fragments

Pag. 79

Leccin 12 Action Bar: Introduccin, Tabs

Pag. 80

Leccin 13 Mens: Mens y Sub Mens bsicos, Mens contextuales, Opciones Avanzadas

Pag. 90

Leccin 14 Widgets

Pag. 94

Leccin 15 Preferencias: SharedPreferences, PreferenceActivity

Pag. 102

Leccin 16 Localizacin: Mecanismos, Proveedores, GPS

Pag. 104

Leccin 17 Mapas : Comparacin v1 y v2, Introduccin v2, Objeto Google Map, Mtodos

Pag. 111

Leccin 18 Notificaciones: Toast, Barra de Estado, Dilogos

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Paso 2. Descargar e instalar Eclipse.


Eclipse es un IDE (Integrated Development Environment) , Ambiente Integrgrado de Desarrollo para mltiples
lenguajes de Programacin y es muy utilizado con el lenguaje Java. Se puede descargar por ejemplo la versin
4.2.1 [Eclipse Juno SR1], o cualquier versin ms actualizada desde http://www.eclipse.org/downloads/. Se
requiere instalar la versin Eclipse IDE for Java Developers, y por supuesto descargar la versin apropiada para el
sistema de operacin (Windows/Mac OS/Linux, y 32/64 bits).
La instalacin consiste simplemente en descomprimir el zip descargado en la ubicacin deseada. Para ejecutarse se
accede al archivo eclipse.exe dentro de la ruta donde se haya descomprimido la aplicacin, por
ejemplo c:\eclipse\eclipse.exe. Durante la primera ejecucin de la aplicacin sepreguntar cul ser la carpeta
donde se requiere almacenar los proyectos. Se indicara la ruta deseada y se marcara un check Use this as the
default para que no vuelva a preguntarlo.

Paso 3. Descargar el SDK de Android.


El SDK Software Development Kit, Herramaienta de Desarrollo de Softwarte, de la plataforma Android se puede
descargar desde http://developer.android.com/sdk/index.html (por ejemplo se puede utilizar la versin r21, que

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

Manual Mca006

Paso 6. Instalar las Platform Tools y los Platforms necesarios.


Adems del SDK de Android comentado en el paso 2, que contiene las herramientas bsicas para desarrollar en
Android, tambin se deben descargar las llamadas Platflorm Tools, que contiene herramientas especficas de la
ltima versin de la plataforma, y una o varias plataformas (SDK Platforms) de Android, que no son ms que las
libreras necesarias para desarrollar sobre cada una de las versiones concretas de Android. As, si se requiere
desarrollar por ejemplo para Android 2.2 se tendr que descargar su plataforma correspondiente. Se recomienda
instalar al menos 2 plataformas: la correspondiente a la ltima versin disponible de Android, y la correspondiente
a la mnima versin de Android que se requiere soporte la aplicacin.
Para ello, desde Eclipse se debe acceder al men Window / Android SDK Manager. En la lista de paquetes
disponibles se seleccionan las Android SDK Platform-tools, las plataformas Android 4.2 (API 17) y Android 2.2
(API 8), y el paquete extra Android Support Library, que es una librera permintiendo utilizar en versiones
antiguas de Android caractersticas introducidas por versiones ms recientes. Se pulsa el botn Install packages
y se espera a que finalice la descarga.

Paso 7. Configurar un AVD.


A la hora de probar y depurar aplicaciones Android no se tiene que hacer necesariamente sobre un dispositivo
fsico, sino que se puede configurar un emulador o dispositivo virtual (Android Virtual Device, o AVD) donde poder
realizar fcilmente estas tareas. Para ello, se accede al AVD Manager (men Window / AVD Manager), y en la

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Estructura de un proyecto Android

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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).

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

10

Manual Mca006

/res/drawable/

Contiene las imgenes [y otros elementos grficos] usados en por la


aplicacin. Para definir diferentes recursos dependiendo de la resolucin y
densidad de la pantalla del dispositivo se suele dividir en varias subcarpetas:

/drawable-ldpi (densidad baja)

/drawable-mdpi (densidad media)

/drawable-hdpi (densidad alta)

/drawable-xhdpi (densidad muy alta)

/res/layout/

Contiene los archivos de definicin XML de las diferentes pantallas de la


interfaz grfica. Para definir distintos layouts dependiendo de la orientacin
del dispositivo se puede dividir en dos subcarpetas:

/res/anim/

/layout (vertical)

/layout-land (horizontal)

Contienen la definicin de las animaciones utilizadas por la aplicacin.

/res/animator/

/res/color/

Contiene archivos XML de definicin de colores segn estado.

/res/menu/

Contiene la definicin XML de los mens de la aplicacin.

/res/xml/

Contiene otros archivos XML de datos utilizados por la aplicacin.

/res/raw/

Contiene recursos adicionales, normalmente en formato distinto a XML, que


no se incluyan en el resto de carpetas de recursos.

/res/values/

Contiene otros archivos XML de recursos de la aplicacin, como por ejemplo


cadenas de texto (strings.xml), estilos (styles.xml), colores (colors.xml),
arreglos de valores (arrays.xml), etc.

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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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!.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

13

Manual Mca006

El elemento ms importante de los archivos generados es R.java, donde se define la clase R.


La clase R contiene las constantes con los ID de todos los recursos de la aplicacin incluidos en la carpeta /res/, de
forma que se pueda acceder fcilmente a estos recursos desde el cdigo a travs de el ID. As, por ejemplo, la
constante R.drawable.ic_launcher contendr el ID de la imagen ic_launcher.png contenida en la carpeta
/res/drawable/. A continuacin como ejemplo se muestra la clase R creada por defecto para un proyecto nuevo:
package gala.curso;
public final class R {
public static final class attr {
}
public static final class dimen {
/** Default screen margins, per the Android Design guidelines.
Customize dimensions originally defined in res/values/dimens.xml (such as
screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
*/
public static final int activity_horizontal_margin=0x7f040000;
public static final int activity_vertical_margin=0x7f040001;
}
public static final class drawable {
public static final int ic_launcher=0x7f020000;
}
public static final class id {

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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>

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

16

Manual Mca006
</manifest>
LECCION 3

Componentes de una aplicacin Android

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

17

Manual Mca006
LECCION 4

Desarrollando la primera aplicacin en Android

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 resultado de presionar el botn Bienvenido es la muestra de la siguiente actividad

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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: " />

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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 :.

<?xml version="1.0" encoding="utf-8"?>


<resources>

<string name="curso">Indique el codigo del curso : </string>

</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;

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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;

public class BienvenidoActivity extends Activity {


@Override
protected void onCreate(Bundle savedInstanceState) {
// cdigo defecto
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bienvenido);
//Localizar los controles
TextView TvBienvenido = (TextView)findViewById(R.id.TvBienvenido);
//Se Recupera la informacin pasada en el intent
Bundle bundle = this.getIntent().getExtras();
//Se Construye el mensaje a mostrar
TvBienvenido.setText("Bienvenido al Curso " + bundle.getString("CURSO"));

}
}
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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Layouts: Frame, Linear, Table, Grid , Relative

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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">

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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" />

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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" >

<TextView android:text="Celda 1.1" />


<TextView android:text="Celda 1.2" />
<TextView android:text="Celda 1.3" />

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

28

Manual Mca006

<TextView android:text="Celda 2.1" />


<TextView android:text="Celda 2.2" />
<TextView android:text="Celda 2.3" />

<TextView android:text="Celda 3.1"


android:layout_columnSpan="2" />

<TextView android:text="Celda 3.2" />

</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>

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

29

Manual Mca006

En el ejemplo, el botn BtnAceptar se colocar debajo del cuadro de


texto TxtNombre(android:layout_below=@id/TxtNombre) y alineado a la derecha del layout padre
(android:layout_alignParentRight=true)

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.

Posicin relativa al layout padre:

android:layout_alignParentLeft.
android:layout_alignParentRight.
android:layout_alignParentTop.
android:layout_alignParentBottom.
android:layout_centerHorizontal.
android:layout_centerVertical.
android:layout_centerInParent.

Opciones de margen (tambin disponibles para el resto de layouts):

android:layout_margin.
android:layout_marginBottom.
android:layout_marginTop.
android:layout_marginLeft.
android:layout_marginRight.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Controles: Propiedades, Eventos, Personalizacin

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;

Luego desde cualquier parte de la aplicacin se puede acceder a cada control


final EditText etCurso = (EditText)findViewById(R.id.EtCurso);
final Button bBienvenido = (Button)findViewById(R.id.BBienvenido);

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

<?xml version="1.0" encoding="UTF-8"?>

<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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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).

LECCION 7 Controles bsicos: Button, TogleButton, ImageButton, ImageView, TextView, EditText,


Objetos Tipo Spanned, Formatos en objetos de texto, CheckBox, RadioBotton
El SDK de Android proporciona tres tipos de botones: el clsico (Button), el de tipo on/off (ToggleButton), y el
que puede contener una imagen (ImageButton). En la imagen siguiente vemos el aspecto por defecto de estos
tres controles.

Control Button http://developer.android.com/reference/android/widget/Button.html

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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" />

Control ToggleButton http://developer.android.com/reference/android/widget/ToggleButton.html

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" />

Control ImageButton http://developer.android.com/reference/android/widget/ImageButton.html


En un control de tipo ImageButton se puede definir una imagen a mostrar en vez de un texto, para lo que se debe
asignar la propiedad android:src. Normalmente se asigna esta propiedad con el descriptor de algn recurso
incluido en la carpeta /res/drawable. As, por ejemplo, se tiene una imagen llamada ok.png y se hace
referencia al recurso @drawable/ok. Adicionalmente, al tratarse de un control de tipo imagen tambin se debera
asignar la propiedad android:contentDescription con una descripcin textual de la imagen, de forma que la
aplicacin sea lo ms accesible posible.

<ImageButton android:id="@+id/BBoton3"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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" />

El botn mostrado en este caso sera similar a ste:

Control ImageView http://developer.android.com/reference/android/widget/ImageView.html

El control ImageView permite mostrar imgenes en la aplicacin. La propiedad ms interesante es android:src,


que permite indicar la imagen a mostrar. Nuevamente, lo normal ser indicar como origen de la imagen el
identificador de un recurso de la carpeta /res/drawable, por ejemplo android:src=@drawable/unaimagen.
Adems de esta propiedad, existen algunas otras tiles en algunas ocasiones como las destinadas a establecer el
tamao mximo que puede ocupar la imagen, android:maxWidth y android:maxHeight, o para indicar cmo
debe adaptarse la imagen al tamao del control, android:scaleType (5=CENTER, 6=CENTER_CROP,
7=CENTER_INSIDE, ). Adems, al tratarse de un control de tipo imagen se debe establecer siempre la propiedad
android:contentDescription para ofrecer una breve descripcin textual de la imagen, algo que har la aplicacin
mucho ms accesible.

<ImageView android:id="@+id/IVFoto"

android:layout_width="wrap_content"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

ImageView iv= (ImageView)findViewById(R.id.IVFoto);

iv.setImageResource(R.drawable.icon);

Control TextView http://developer.android.com/reference/android/widget/TextView.html

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:text="@string/escribe_algo Escribe algo:"

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().

final TextView lEtiqueta = (TextView)findViewById(R.id.LEtiqueta);

String texto = lEtiqueta.getText().toString();

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

36

Manual Mca006

texto += "123";

lEtiqueta.setText(texto);

lEtiqueta.setBackgroundColor(Color.BLUE);

Control EditText http://developer.android.com/reference/android/widget/EditText.html

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

TypefaceSpan. Modifica el tipo de fuente.


StyleSpan. Modifica el estilo del texto (negrita, cursiva, ).
ForegroudColorSpan. Modifica el color del texto.
AbsoluteSizeSpan. Modifica el tamao de fuente.

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();

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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;

//...

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

ArrayAdapter. Es el ms sencillo de todos los adaptadores, y provee de datos a un control de seleccin a


partir de un array de objetos de cualquier tipo.

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"};

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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 array que contiene los datos a mostrar.

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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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]);
}

public void onNothingSelected(AdapterView<?> parent) {


lblMensaje.setText("");
}
});

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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).

LECCION 9 Controles personalizados: Extendiendo la funcin de un control existente, Combinando


varios controles para crear uno ms complejo, Diseando un control desde cero
En ocasiones se requiere crear controles personalizados, diseados a la medida de los requerimientos.
Android permite crear controles personalizados, y permite hacerlo de tres formas diferentes:

Extendiendo la funcionalidad de un control ya existente.

Combinando varios controles para formar otro ms complejo.

Diseando desde cero un nuevo control.

Extendiendo la funcin de un control existente

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);
}

public ExtendedEditText(Context context, AttributeSet attrs) {


super(context, attrs);

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

46

Manual Mca006
}

public ExtendedEditText(Context context) {


super(context);
}
Para modificar el aspecto del control aadiendo el contador de caracteres se sobreescribe el evento onDraw(),
invocado por Android cada vez se redibuja el control en pantalla. Este mtodo recibe como parmetro un objeto
Canvas, el lienzo donde se dibujan todos los elementos extra necesarios en el control. El objeto Canvas,
proporciona una serie de mtodos para dibujar cualquier tipo de elemento (lineas, rectngulos, elipses, texto,
bitmaps, ) sobre el espacio ocupado por el control.
private void inicializacion()
{
Paint p1 = new Paint(Paint.ANTI_ALIAS_FLAG);
p1.setColor(Color.BLACK);
p1.setStyle(Style.FILL);

Paint p2 = new Paint(Paint.ANTI_ALIAS_FLAG);


p2.setColor(Color.WHITE);
p2.setTextSize(20);
}
Se debe tener en cuenta es que todos los mtodos de dibujo reciben las unidades en pixeles y por tanto si se
utilizan valores fijos se tendran problemas al visualizar los resultados en pantallas con distintas densidades de
pxeles. Para evitar esto en lo posible, se convierten los valores de pxeles a algn valor dependiente de la
densidad de la pantalla, lo que en Android se puede conseguir multiplicando los pxeles por un factor de escala con
los mtodos getResources().getDisplayMetrics().density.
private void inicializacion()
{
//...

escala = getResources().getDisplayMetrics().density;
}

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

47

Manual Mca006
//...

@Override
public void onDraw(Canvas canvas)
{
//llamada al mtodo base
super.onDraw(canvas);

// Se dibuja el fondo negro del contador


canvas.drawRect(this.getWidth()-30*escala, 5*escala,
this.getWidth()-5*escala, 20*escala, p1);

//Se dibuja el nmero de caracteres sobre el contador


canvas.drawText("" + this.getText().toString().length(),
this.getWidth()-28*escala, 17*escala, p2);
}
A estos mtodos se les pasa como parmetro las coordenadas del elemento a dibujar relativas al espacio ocupado
por el control y el pincel a utilizar en cada caso.

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.

En Android 2 con densidad de pantalla baja:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

48

Manual Mca006

En Android 4 con densidad de pantalla alta:

Combinando varios controles para crear un control ms complejo

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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;

//...

public class ControlLogin extends LinearLayout


{
public ControlLogin(Context context) {
super(context);
inicializar();
}

public ControlLogin(Context context, AttributeSet attrs) {


super(context, attrs);
inicializar();

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

Para Android 4.x se veramos as:

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);
}

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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;

public interface OnLoginListener


{
void onLogin(String usuario, String password);
}
A continuacin, se aade un nuevo miembro de tipo OnLoginListener a la clase ControlLogin, y un mtodo pblico
para suscribirse al nuevo evento.
public class ControlLogin extends LinearLayout
{
private OnLoginListener listener;
//...
public void setOnLoginListener(OnLoginListener l)
{
listener = l;
}
}
La aplicacin principal puede suscribirse al evento OnLogin y ejecutar el cdigo cuando ste se genere.La
implementacin del evento se colocar en el mtodo asignarEventos definido previamente:.

private void asignarEventos()

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.");
}
});

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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();

// Procesamos los atributos XML personalizados


TypedArray a =
getContext().obtainStyledAttributes(attrs,
R.styleable.ControlLogin);

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

56

Manual Mca006

String textoBoton = a.getString(


R.styleable.ControlLogin_login_text);
btnLogin.setText(textoBoton);
a.recycle();
}
Slo queda utilizarlo. Para ello se debe declarar un nuevo espacio de nombres (namespace) local para el paquete
java utilizado, ejemplo gala:
xmlns:gala="http://schemas.android.com/apk/res/com.gala.android.controlpers2"

<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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

57

Manual Mca006

En Android 4 se visualizara de forma prcticamente idntica:

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.

EXACTLY: indica que al control se le dar exactamente 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);

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

58

Manual Mca006
int alto = calcularAlto(heightMeasureSpec);
setMeasuredDimension(ancho, alto);
}

private int calcularAlto(int limitesSpec)


{
int res = 100; //Alto por defecto
int modo = MeasureSpec.getMode(limitesSpec);
int limite = MeasureSpec.getSize(limitesSpec);
if (modo == MeasureSpec.AT_MOST) {
res = limite;
}
else if (modo == MeasureSpec.EXACTLY) {
res = limite;
}
return res;
}

private int calcularAncho(int limitesSpec)


{
int res = 200; //Ancho por defecto
int modo = MeasureSpec.getMode(limitesSpec);
int limite = MeasureSpec.getSize(limitesSpec);
if (modo == MeasureSpec.AT_MOST) {
res = limite;
}
else if (modo == MeasureSpec.EXACTLY) {
res = limite;
}
return res;

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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);

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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();

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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 interface OnColorSelectedListener


{
void onColorSelected(int color);
}
Posteriormente, se definiremos un objeto de este tipo como atributo del control y se escribe un nuevo mtodo
permitiendo a las aplicaciones suscribirse al evento:
public class SelectorColor extends View
{
private OnColorSelectedListener listener;

//...
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)
{

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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()

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

63

Manual Mca006
{
@Override
public void onColorSelected(int color)
{
//Aqu se tratara el color seleccionado (parmetro 'color'
//...
}
});
}
}

LECCION 10 Pestaas (Tabs)


Dado el poco espacio con el que se cuenta en las pantallas de muchos dispositivos, o simplemente por cuestiones
de organizacin, a veces es necesario/interesante dividir los controles en varias pantallas. Y una de las formas
clsicas de conseguir esto consiste en la distribucin de los elementos por pestaas o tabs. Android permite utilizar
este tipo de interfaces, aunque lo hace de una forma un tanto peculiar, ya que la implementacin no va a depender
de un slo elemento sino de varios, que adems deben estar distribuidos y estructurados de una forma
determinada nada arbitraria. Adicionalmente no bastar simplemente con definir la interfaz en XML, sino que
tambin se necesita completar el conjunto con algunas lneas de cdigo.
En Android, el elemento principal de un conjunto de pestaas ser el control TabHost. ste va a ser el contenedor
principal del conjunto de pestaas y deber tener obligatoriamente como id el valor @android:id/tabhost. Dentro
de ste se va a incluir un LinearLayout que servir para distribuir verticalmente las secciones principales del layout:
la seccin de pestaas en la parte superior y la seccin de contenido en la parte inferior. La seccin de pestaas se
representar mediante un elemento TabWidget, que deber tener como id el valor @android:id/tabs, y como
contenedor para el contenido de las pestaas se aadir un FrameLayout con el id obligatorio
@android:id/tabcontent. Por ltimo, dentro del FrameLayout se incluira el contenido de cada pestaa,
normalmente cada uno dentro de su propio layout principal y con un id nico que permita posteriormente hacer
referencia a ellos fcilmente. A continuacin se representa de forma grfica toda la estructura descrita.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

64

Manual Mca006

El archivo XML con esta estructura sera:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">

<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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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>

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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() {

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

70

Manual Mca006

A continuacin se muestra el cdigo de la clase


package com.gala.android.fragments;
import android.app.Activity;
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.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class FragmentListado extends Fragment {


private Correo[] datos =
new Correo[]{
new Correo("Persona 1", "Asunto del correo 1", "Texto del correo 1"),
new Correo("Persona 2", "Asunto del correo 2", "Texto del correo 2"),
new Correo("Persona 3", "Asunto del correo 3", "Texto del correo 3"),
new Correo("Persona 4", "Asunto del correo 4", "Texto del correo 4"),
new Correo("Persona 5", "Asunto del correo 5", "Texto del correo 5")};
private ListView lstListado;

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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));
}

class AdaptadorCorreos extends ArrayAdapter<Correo> {


Activity context;
AdaptadorCorreos(Fragment context) {
super(context.getActivity(), R.layout.listitem_correo, datos);
this.context = context.getActivity();
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View item = inflater.inflate(R.layout.listitem_correo, null);
TextView lblDe = (TextView)item.findViewById(R.id.LblDe);
lblDe.setText(datos[position].getDe());
TextView lblAsunto = (TextView)item.findViewById(R.id.LblAsunto);
lblAsunto.setText(datos[position].getAsunto());
return(item);
}
}
}

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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;

public class FragmentDetalle extends Fragment {


@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_detalle, container, false);

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

Pantalla normal (Galaxy Nexus 4.7 pulgadas):

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

77

Manual Mca006

Pantalla grande vertical (Nexus 7 7.3 pulgadas):

Pantalla grande horizontal (Nexus 7 7.3 pulgadas):

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

79

Manual Mca006

el ttulo de la actividad actual (definido en el AndroidManifest mediante el atributo android:label de cada


elemento <activity>).

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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!");;

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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>

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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);

SubMenu smnu = menu.


addSubMenu(Menu.NONE, MNU_OPC1, Menu.NONE, "Opcion3")
.setIcon(android.R.drawable.ic_menu_agenda);
smnu.add(Menu.NONE, SMNU_OPC1, Menu.NONE, "Opcion 3.1");
smnu.add(Menu.NONE, SMNU_OPC2, Menu.NONE, "Opcion 3.2");

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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);

//Obtenemos las referencias a los controles


lblMensaje = (TextView)findViewById(R.id.LblMensaje);

//Asociamos los mens contextuales a los controles


registerForContextMenu(lblMensaje);
}
Luego se sobreescribe en la actividad el evento encargado de construir los mens contextuales asociados a los
diferentes controles de la aplicacin. En este caso el evento se llama onCreateContextMenu(), y a diferencia
de onCreateOptionsMenu() ste se llama cada vez que se necesita mostrar un men contextual, y no una sola vez
al inicio de la aplicacin. En este ejemplo se defineun men en XML llamado menu_ctx_etiqueta.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/CtxLblOpc1"
android:title="OpcEtiqueta1"></item>
<item android:id="@+id/CtxLblOpc2"
android:title="OpcEtiqueta2"></item>

</menu>
Por su parte el evento onCreateContextMenu() queda de la siguiente forma:
@Override

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

85

Manual Mca006
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, v, menuInfo);

MenuInflater inflater = getMenuInflater();


inflater.inflate(R.menu.menu_ctx_etiqueta, menu);
}
Por ltimo, para implementar las acciones a realizar tras pulsar una opcin determinada del men contextual se
implementa el evento onContextItemSelected() :
@Override
public boolean onContextItemSelected(MenuItem item) {

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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);

//Ocultar todo el grupo


mnu.setGroupVisible(R.id.grupo1, false);
Adems de estas acciones, tambin se puede modificar el comportamiento de las opciones del grupo de forma que
tan slo se pueda seleccionar una de ellas, o para que se puedan seleccionar varias. Con esto, se convierte el
grupo de opciones de men en el equivalente a un conjunto de
controles RadioButton o CheckBox respectivamente. Esto se logra utilizando el
atributo android:checkableBehavior del elemento <group>, al que se puede asignar el valor single (seleccin

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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;

//...

private void construirMenu(Menu menu)


{
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);

SubMenu smnu = menu.addSubMenu(Menu.NONE, MNU_OPC3, Menu.NONE, "Opcion3")


.setIcon(android.R.drawable.ic_menu_agenda);

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

88

Manual Mca006

smnu.add(GRUPO_MENU_1, SMNU_OPC1, Menu.NONE, "Opcion 3.1");


smnu.add(GRUPO_MENU_1, SMNU_OPC2, Menu.NONE, "Opcion 3.2");

//Establecemos la seleccin exclusiva para el grupo de opciones


smnu.setGroupCheckable(GRUPO_MENU_1, true, true);

//Marcamos la opcin seleccionada actualmente


if(opcionSeleccionada == 1)
smnu.getItem(0).setChecked(true);
else if(opcionSeleccionada == 2)
smnu.getItem(1).setChecked(true);
}

@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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

90

Manual Mca006

Los pasos principales para la creacin de un widget Android son los siguientes:

Definicin de su interfaz grfica (layout).

Configuracin XML del widget (AppWidgetProviderInfo).

Implementacin de la funcionalidad del widget (AppWidgetProvider) , especialmente el evento de


actualizacin.

Declaracin del widget en el Android Manifest de la aplicacin.


El archivo se llamar miwidget.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:padding="10dp"
android:layout_margin="5dp" >
<FrameLayout android:id="@+id/frmWidget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:padding="5dp" >

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

Contenedores: FrameLayout, LinearLayout, RelativeLayout y GridLayout (ste ltimo a partir de Android


4).

Controles: Button, ImageButton, ImageView, TextView, ProgressBar,Chronometer, AnalogClock y ViewFlip


per. A partir de Android 3 tambin se puede utilizar ListView, GridView, StackView y AdapterViewFlipper,
aunque su uso tiene algunas particularidades.

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:

initialLayout: referencia al layout XML creado en el paso anterior.

minWidth: ancho mnimo del widget en pantalla, en dp (density-independent pixels).

minHeight: alto mnimo del widget en pantalla, en dp (density-independent pixels).

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

92

Manual Mca006

label: nombre del widget que semostrar en el men de seleccin de Android.

updatePeriodMillis: frecuencia de actualizacin del widget, en milisegundos.

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:

ancho_mnimo = (num_celdas * 70) 30


alto_mnimo = (num_celdas * 70) 30
Atendiendo a esta frmula, si se requiere el widget ocupe por ejemplo un tamao mnimo de 2 celdas de ancho
por 1 celda de alto, se deben indicar unas dimensiones de 110dp x 40dp.

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:

onEnabled(): lanzado cuando se crea la primera instancia de un widget.


onUpdate(): lanzado periodicamente cada vez que se debe actualizar un widget, por ejemplo cada vez que se
cumple el periodo de tiempo definido por el parmetroupdatePeriodMillis antes descrito, o cuando se aade el
widget al escritorio.
onDeleted(): lanzado cuando se elimina del escritorio una instancia de un widget.
onDisabled(): lanzado cuando se elimina del escritorio la ltima instancia de un widget.
En la mayora de los casos, se debe implementar como mnimo el evento onUpdate(). El resto de mtodos
dependern de la funcionalidad del widget.
package com.gala.android.widgets;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;

public class MiWidget extends AppWidgetProvider {

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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");

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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" />

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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));

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

101

Manual Mca006

LECCION 16 Localizacin: Mecanismos, Proveedores, GPS


La localizacin geogrfica en Android es uno de esos servicios que, a pesar de requerir poco cdigo para ponerlos
en marcha, no son para nada intuitivos ni fciles de llegar a comprender por completo. Y esto no es debido al
diseo de la plataforma Android en s, sino a la propia naturaleza de este tipo de servicios. Por un lado, existen
multitud de formas de obtener la localizacin de un dispositivo mvil, aunque la ms conocida y popular es la
localizacin por GPS, tambin es posible obtener la posicin de un dispositivo por ejemplo a travs de las antenas
de telefona mvil o mediante puntos de acceso Wi-Fi cercanos, y todos cada uno de estos mecanismos tiene una
precisin, velocidad y consumo de recursos distinto. Por otro lado, el modo de funcionamiento de cada uno de
estos mecanismos hace que su utilizacin desde el cdigo no sea todo lo directa e intuitiva que se deseara.

Qu mecanismos de localizacin se tienen disponibles?


Lo primero que debe conocer una aplicacin que necesite obtener la localizacin geogrfica es qu mecanismos de
localizacin (proveedores de localizacin, o location providers) tiene disponibles en el dispositivo.
La forma ms sencilla de saber los proveedores disponibles en el dispositivo es mediante una llamada al mtodo
getAllProviders() de la clase LocationManager, clase principal a la hora de utilizar la API de localizacin de Android.
Para ello, se obtiene una referencia al location manager llamando a getSystemService(LOCATION_SERVICE), y
posteriormente se obtiene la lista de proveedores mediante el mtodo citado para obtener la lista de nombres de
los proveedores:
LocationManager locManager = (LocationManager)getSystemService(LOCATION_SERVICE);
List<String> listaProviders = locManager.getAllProviders();
Una vez obtenida la lista completa de proveedores disponibles se puede acceder a las propiedades de cualquiera de
ellos (precisin, coste, consumo de recursos, o si es capaz de obtener la altitud, la velocidad, ). As, se puede
obtener una referencia al provider mediante su nombre llamando al mtodo getProvider(nombre) y posteriormente
utilizar los mtodos disponibles para conocer sus propiedades, por ejemplo getAccuracy() para saber su precisin
(se tienen disponibles las constantes Criteria.ACCURACY_FINE para precisin alta, y Criteria.ACCURACY_COARSE
para precisin media), supportsAltitude() para saber si obtiene la altitud, o getPowerRequirement() para obtener el
nivel de consumo de recursos del proveedor. La lista completa de mtodos para obtener las caractersticas de un
proveedor se puede consultar en la documentacin oficial de la clase LocationProvider.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

102

Manual Mca006

LocationManager locManager = (LocationManager)getSystemService(LOCATION_SERVICE);


List<String> listaProviders = locManager.getAllProviders();

LocationProvider provider = locManager.getProvider(listaProviders.get(0));


int precision = provider.getAccuracy();
boolean obtieneAltitud = provider.supportsAltitude();
int consumoRecursos = provider.getPowerRequirement();
Al margen de esto, hay que tener en cuenta que la lista de proveedores devuelta por el mtodo getAllProviders()
contendr todos los proveedores de localizacin conocidos por el dispositivo, incluso si stos no estn permitidos
(segn los permisos de la aplicacin) o no estn activados, por lo que esta informacin puede no ser de mucha
ayuda.
Qu proveedor de localizacin es mejor para la aplicacin?
Android proporciona un mecanismo alternativo para obtener los proveedores que cumplen unos determinados
requisitos entre todos los disponibles. Para ello es posible definir un criterio de bsqueda, mediante un objeto de
tipo Criteria, en el que se indican las caractersticas mnimas del proveedor a utilizar. As, por ejemplo, para buscar
uno con precisin alta y que proporcione la altitud se definira el siguiente criterio de bsqueda:
Criteria req = new Criteria();
req.setAccuracy(Criteria.ACCURACY_FINE);
req.setAltitudeRequired(true);
Tras esto, se puede utilizar los mtodos getProviders() o getBestProvider() para obtener la lista de proveedores
que se ajustan mejor al criterio definido o el proveedor que mejor se ajusta a dicho criterio, respectivamente.
Adems, ambos mtodos reciben un segundo parmetro que indica si se requiere que slo se devuelvan los
proveedores que estn activados actualmente.
//Mejor proveedor por criterio
String mejorProviderCrit = locManager.getBestProvider(req, false);
//Lista de proveedores por criterio
List<String> listaProvidersCrit = locManager.getProviders(req, false);
Con esto, ya se tiene una forma de seleccionar en cada dispostivo aquel proveedor que mejor se ajusta a las
necesidades.
Est disponible y activado un proveedor determinado?
Aunque existe la posibilidad de buscar dinmicamente proveedores de localizacin segn un determinado criterio
de bsqueda, es bastante comn que la aplicacin est diseada para utilizar uno en concreto, por ejemplo el GPS,
y por tanto se necesitar algn mecanismo para saber si ste est activado o no en el dispositivo. Para esta tarea,
la clase LocationManager nos proporciona otro mtodo llamado isProviderEnabled() que permite hacer
exactamente lo requerido. Para ello, de debe pasarle el nombre del provider a consultar. Para los ms comunes
existen varias constantes ya definidas:
LocationManager.NETWORK_PROVIDER. Localizacin por la red de telefona.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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"/>

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

110

Manual Mca006

LECCION 18 Notificaciones: Toast, Barra de Estado, Dilogos


Toast
En Android existen varias formas de notificar mensajes al usuario, como por ejemplo los cuadros de dilogo
modales o las notificaciones de la bandeja del sistema (o barra de estado).
Un toast es un mensaje que se muestra en pantalla durante unos segundos al usuario para luego volver a
desaparecer automticamente sin requerir ningn tipo de actuacin por su parte, y sin recibir el foco en ningn
momento (o dicho de otra forma, sin interferir en las acciones que est realizando el usuario en ese momento).
Aunque son personalizables, aparecen por defecto en la parte inferior de la pantalla, sobre un rectngulo gris
ligeramente translcido. Por sus propias caractersticas, este tipo de notificaciones son ideales para mostrar
mensajes rpidos y sencillos al usuario, pero por el contrario, al no requerir confirmacin por su parte, no deberan
utilizarse para hacer notificaciones demasiado importantes.
Su utilizacin es muy sencilla, concentrndose toda la funcionalidad en la clase Toast. Esta clase dispone de un
mtodo esttico makeText() al que se pasa como parmetro el contexto de la actividad, el texto a mostrar, y la
duracin del mensaje, que puede tomar los valores LENGTH_LONG o LENGTH_SHORT, dependiendo del tiempo que
se requiera que la notificacin aparezca en pantalla. Tras obtener una referencia al objeto Toast a travs de este
mtodo, slo queda mostrarlo en pantalla mediante el mtodo show().

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

111

Manual Mca006

Como ejemplo se incluye un botn que muestre un toast bsico:


btnDefecto.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Toast toast1 =
Toast.makeText(getApplicationContext(),
"Toast por defecto", Toast.LENGTH_SHORT);

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() {

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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"

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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());

LayoutInflater inflater = getLayoutInflater();


View layout = inflater.inflate(R.layout.toast_layout,
(ViewGroup) findViewById(R.id.lytLayout));

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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.";

Intent notIntent = new Intent(contexto,


AndroidNotificacionesActivity.class);

PendingIntent contIntent = PendingIntent.getActivity(


contexto, 0, notIntent, 0);

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;

//Aadir sonido, vibracin y luces


//notif.defaults |= Notification.DEFAULT_SOUND;
//notif.defaults |= Notification.DEFAULT_VIBRATE;

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

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:

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

118

Manual Mca006

Por ltimo, si se pulsa sobre la notificacin se debera abrir de nuevo automticamente la aplicacin de ejemplo.

Todos los derechos reservados, prohibida la reproduccin, Instituto Gala de Venezuela

119

S-ar putea să vă placă și