El objetivo de este tutorial es iniciarse en la programacin de Android. Se requieren conceptos
previos de programacin en J ava. Se busca ir conociendo los rudimentos bsicos de la programacin en Android presentando los conceptos con ejercicios resueltos e invitando a la resolucin de otros problemas propuesto.
Descarga de herramientas necesarios para programar para Android.
1 - Primero debemos instalar el compilador de J ava y la mquina virtual. Estas herramientas las podemos descargar de: J ava SE Development Kit (J DK).
2 - El segundo paso es la descarga del editor Eclipse, lo hacemos del sitio: Eclipse IDE for J ava Developers.
3 - El tercer paso es descargar el SDK Android, lo podemos descargar de: SDK de Android
El archivo que descargaremos es el zip: android-sdk_rxx-windows. (donde xx es el nmero de la ltima versin) Descomprimimos el archivo y lo ubicamos en la raiz de la unidad c\:, luego de descomprimir tenemos una carpeta llamada: c:\android-sdk-windows
4 - El cuarto paso es ejecutar el programa: c:\android-sdk-windows\SDK Manager.exe que se encuentra en la carpeta que acabamos de descomprimir el SDK de Android. Aparece esta ventana (presionamos cancelar con el objetivo de seleccionar una AVD (Android Virtual Device) y no tener que esperar una eternidad descargando todas las versiones de AVD):
Instalaremos en primera instancia la versin del SDK 2.3.3 (la lnea 2 est orientada al desarrollo de aplicaciones para celulares y la lnea 3 est orientada a tablet). Seleccionamos Available packages y luego del lado derecho solo dejamos tildado la versin del SDK 2.3.3 (ms adelante podemos instalar otras versiones de Android) Por ltimo procedemos a presionar el botn "Install Selected":
Aparece un dilogo donde nos informa el progreso de instalacin:
Ahora ya podemos cerrar la aplicacin del SDK Manager.exe.
5 - Instalacin del plugin de Eclipse para trabajar con Android.
Para instalar el plugin ingresamos al entorno Eclipse. Luego desde el men de opciones: Help-> Install New Software, aparece el siguiente dilogo, presionamos el botn add y disponemos la url donde se encuentra el plugin:
En Location disponemos la url: https://dl-ssl.google.com/android/eclipse/
Tildamos "Developer Tools", presionamos seguidamente el botn "Next" dos veces hasta que aparece la ventana donde tenemos que aceptar los "Trminos y Condiciones" y presionamos el botn "Finish" Al finalizar la instalacin del plugin se reinicia el Eclipse para que se instale completamente.
6 - El siguiente paso que debemos efectuar para poder empezar a desarrollar aplicaciones para Android es configurar el SDK:
Para esto nos dirigimos a la opcin Windows ->Preferences donde aparece el siguiente dilogo:
Seleccionamos la carpeta donde descomprimimos SDK de Android y presionamos el botn "Apply"
7 - Por ltimo debemos crear el AVD (Android Virtual Device) para ello nos dirigimos a la opcin Window ->Android SDK and AVD Manager.
En este dilogo debemos crear el emulador de Android (presionamos el botn New...):
En este dilogo asignamos un nombre a nuestro AVD, lo enlazamos con la versin de SDK respectivo, fijamos un tamao al SD Card:
Ya tenemos todo configurado para el desarrollo de aplicaciones Android. 2 - Pasos para crear el primer proyecto Android
Ya tenemos todo lo necesario instalado para implementar el primer proyecto. Desde el men de opciones: File ->New ->Android Project
En este dilogo especificamos el nombre del proyecto y el nombre del paquete java donde se almacenarn los archivos java que creemos. El plugin de Android nos genera todos los directorios y archivos bsicos para iniciar nuestro proyecto:
No haremos en este momento un anlisis del significado y objetivo de cada uno de estos directorios y archivos generados, sino a medida que avancemos con este curso iremos viendo en forma puntual y profunda.
La interfaz visual de nuestro programa para Android se almacena en un archivo XML en la carpeta res, subcarpeta layout y el archivo se llama main.xml. En esta carpeta tenemos creada nuestra primer pantalla.
Al seleccionar este archivo el plugin de Android nos permite visualizar el contenido en "vista de diseo (Graphical Layout)":
Si seleccionamos la otra pestaa podemos visualizar el archivo main.xml en formato de texto:
El plugin Android ya insert un control de tipo LinealLayout que especifica que todos los controles visuales que se inserten se dispondrn uno debajo del otro ya que la propiedad orientation est inicializada con el valor vertical (orientation="vertical")
Ya veremos que podemos modificar todo este archivo para que se adapte a la aplicacin que queremos desarrollar.
Luego contenido en el control LinealLayout hay otro control de tipo TextView que es bsicamente una etiqueta o label que mostrar en pantalla el valor almacenado en la propiedad text. Podemos modificar directamente el archivo xml o en "vista de diseo" modificar los valores de las propiedades. Elegimos nuevamente la pestaa "Graphical Layout" y seleccionamos el TextView con el mouse y presionamos el botn derecho del mouse, buscamos la propiedad text y la cambiamos por la etiqueta: "Mi primer programa para Android":
Con esto ya podemos probar nuestra primer aplicacin para un dispositivo Android. Presionamos Run desde el men o el cono respectivo. Seleccionamos que se ejecute como aplicacin "Android Application". Ahora se abrir el AVD(Android Virtual Device) esto tarda bastante tiempo, es muy importante recordar que luego de ver ejecutndose el programa NO debemos cerrar el AVD para que la prxima ejecucin se inicie ms rpido (podemos minimizar el AVD)
Ahora podemos ver nuestra primer aplicacin corriendo en el emulador de Android:
Como hemos visto el plugin de Eclipse nos genera en forma automtica todas las carpetas y archivos bsicos que necesitamos en un principio. En el siguiente concepto podremos empezar a programar verdaderamente. El nico objetivo de este ejercicio es recordar los pasos para crear un proyecto.
Final del proyecto001.
3 - Captura del clic de un botn
Problema: Realizar la carga de dos nmeros en controles de tipo EditText. Mostrar un mensaje que solicite la carga de los valores. Disponer un Button para sumar los dos valores ingresados. Mostrar el resultado en un tercer TextView. La interfaz visual debe quedar algo semejante a esto:
Veamos paso a paso como creamos la interfaz visual de nuestro programa. Primero borramos el TextView que aparece por defecto cuando se crea un proyecto con el plugin de Android. Ahora desde la ventana "Palette" seleccionamos de la pestaa "Form Widgets" el control "TextView" y lo arrastramos a la ventana de diseo de nuestra interfaz:
Ahora lo seleccionamos y presionamos el botn derecho del mouse sobre la componente y especificamos la propiedad text (como habamos visto anteriormente) disponemos el texto "Ingrese el primer valor:":
Tambin vamos a especificar la propiedad "Id", la misma parece primera en el men contextual:
Le asignaremos como nombre a este objeto: tv1 (recordemos que se trata de un objeto de la clase TextView)
Ahora de la paleta de componentes seleccionamos la pestaa "Text Fields" y arrastramos el primero (el que tiene la etiqueta abc)
Presionando el botn derecho sobre el control EditText configuramos la propiedad Id... con el nombre et1 (este nombre haremos referencia posteriormente desde J ava)
Efectuamos los mismos pasos para crear el segundo TextView y EditText (inicializamos las propiedades respectivas) Definimos los id con los nombres tv2 y et2, el resultado visual debe ser algo semejante a esto:
De la pestaa "Form Widgets" arrastramos un control de tipo "Button":
Inicializamos la propiedad text con el texto "Sumar" y la propiedad id la dejamos con el valor ya creado llamado "button1".
Para terminar con nuestra interfaz visual arrastramos un tercer objeto de tipo TextView y definimos la propiedad id con el valor "tv3" y la propiedad text con el texto "resultado", recordemos que la interfaz final debe ser semejante a esta:
Si en este momento ejecutamos la aplicacin aparece la interfaz visual correctamente pero cuando presionemos el botn no mostrar la suma.
Hasta ahora hemos trabajado solo con el archivo xml (main.xml) donde se definen los controles visuales de la ventana que estamos creando.
Abrimos seguidamente el archivo Proyecto002Activity.java que lo podemos ubicar en la carpeta src:
La clase Proyecto002Activity hereda de la clase Activity. La clase Activity representa una ventana de Android y tiene todos los mtodos necesarios para crear y mostrar los objetos que hemos dispuesto en el archivo xml.
El cdigo fuente de la clase Proyecto002Activity.java es:
package andr oi d. pr oyect o002;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e;
publ i c cl ass Pr oyect o002Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; } }
Como mnimo se debe sobrescribir el mtodo onCreate heredado de la clase Activity donde procedemos a llamar la mtodo setContentView pasando como referencia un valor almacenado en una constante llamada main contenida en una clase llamada layout que a su vez la contiene una clase llamada R (veremos ms adelante que el plugin de Eclipse para Android se encarga de crear la clase R en forma automtica y sirve como puente entre el archivo xml y nuestra clase Proyecto002Activity)
Captura de eventos. Ahora viene la parte donde definimos variables en java donde almacenamos las referencias a los objetos definidos en el archivo XML.
Definimos tres variables, dos de tipo EditText y finalmente una de tipo TextView (estas dos clases se declaran en el paquete android.widget, es necesario importar dichas clases para poder definir las variables de dichas clases):
package andr oi d. pr oyect o002;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o002Act i vi t y ext ends Act i vi t y {
pr i vat e Edi t Text et 1, et 2; pr i vat e Text Vi ew t v3;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; } }
Los nombres que le d a los objetos en este caso coinciden con la propiedad id (no es obligatorio):
pr i vat e Edi t Text et 1, et 2; pr i vat e Text Vi ew t v3;
No definimos TextView para los dos mensajes "Ingrese el primer valor" e "Ingrese el segundo valor" ya que no necesitaremos interactuar con ellos. Tambin veremos que el objeto de la clase Button no es necesario definir un atributo sino que desde el archivo XML inicializaremos la propiedad OnClick.
En el mtodo onCreate debemos enlazar estas variables con los objetos definidos en el archivo XML, esto se hace llamando al mtodo findViewById:
publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. et 2) ; t v3=( Text Vi ew) f i ndVi ewByI d( R. i d. t v3) ; }
Al mtodo findViewById debemos pasar la constante creada en la clase R (recordemos que se crea automticamente esta clase) el nombre de la constante si debe ser igual con el nombre de la propiedad del objeto creado en el archivo XML. Como la clase findViewById retorna una clase de tipo View luego debemos utilizar el operador cast (es decir le antecedemos entre parntesis el nombre de la clase)
Ya tenemos almacenados en las variables las referencias a los tres objetos que se crean al llamar al mtodo:setContentView(R.layout.main); .
Ahora planteamos el mtodo que se ejecutar cuando se presione el botn (el mtodo debe recibir como parmetro un objeto de la clase View) En nuestro ejemplo lo llam sumar:
package andr oi d. pr oyect o002;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o002Act i vi t y ext ends Act i vi t y {
pr i vat e Edi t Text et 1, et 2; pr i vat e Text Vi ew t v3;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. et 2) ; t v3=( Text Vi ew) f i ndVi ewByI d( R. i d. t v3) ; }
/ / Est e mt odo se ej ecut ar cuando se pr esi one el bot n publ i c voi d sumar ( Vi ew vi ew) {
} }
Ahora debemos ir al archivo XML e inicializar la propiedad OnClick del objeto button1 con el nombre del mtodo que acabamos de crear (este paso es fundamental para que el objeto de la clase Button pueda llamar al mtodo sumar que acabamos de crear):
Finalmente implementaremos la lgica para sumar los dos valores ingresados en los controles EditText:
publ i c voi d sumar ( Vi ew vi ew) { St r i ng val or 1=et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng val or 2=et 2. get Text ( ) . t oSt r i ng( ) ; i nt nr o1=I nt eger . par seI nt ( val or 1) ; i nt nr o2=I nt eger . par seI nt ( val or 2) ; i nt suma=nr o1+nr o2; St r i ng r esu=St r i ng. val ueOf ( suma) ; t v3. set Text ( r esu) ; }
Extraemos el texto de los dos controles de tipo EditText y los almacenamos en dos variables locales de tipo String. Convertimos los String a tipo entero, los sumamos y el resultado lo enviamos al TextView donde se muestra la suma (previo a convertir la suma a String) La clase completa queda entonces como:
package andr oi d. pr oyect o002;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o002Act i vi t y ext ends Act i vi t y {
pr i vat e Edi t Text et 1, et 2; pr i vat e Text Vi ew t v3;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. et 2) ; t v3=( Text Vi ew) f i ndVi ewByI d( R. i d. t v3) ; }
/ / Est e mt odo se ej ecut ar cuando se pr esi one el bot n publ i c voi d sumar ( Vi ew vi ew) { St r i ng val or 1=et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng val or 2=et 2. get Text ( ) . t oSt r i ng( ) ; i nt nr o1=I nt eger . par seI nt ( val or 1) ; i nt nr o2=I nt eger . par seI nt ( val or 2) ; i nt suma=nr o1+nr o2; St r i ng r esu=St r i ng. val ueOf ( suma) ; t v3. set Text ( r esu) ; } }
Si ejecutamos nuestro programa podemos ver ahora que luego de cargar dos valores al presionar el botn aparece en el tercer TextView el resultado de la suma de los dos EditText:
Final del proyecto002.
4 - Controles RadioGroup y RadioButton
El objetivo de este concepto es practicar la implementacin de un programa que requiera controles de tipo RadioButton para seleccionar una actividad. Aprenderemos como agrupar un conjunto de RadioButton y verificar cual est seleccionado.
Problema: Realizar la carga de dos nmeros en controles de tipo EditText. Mostrar un mensaje que solicite la carga de los valores. Disponer dos controles de tipo RadioButton para seleccionar si queremos sumar o restar dichos valores. Finalmente mediante un control de tipo Button efectuamos la operacin respectiva. Mostramos el resultado en un TextView. El problema es similar al anterior. Para disponer los controles de tipo RadioButton debemos en realidad primero insertar un control de tipo RadioGroup (este control se encuentra en la paleta de componentes en la pestaa FormWidgets):
Cuando arrastramos el control RadioGroup al formulario se generan automticamente 3 objetos de la clase RadioButton contenidos dentro del RadioGroup, podemos fcilmente identificar que los controles RadioButton pertenecen a dicho RadioGroup viendo la ventana de "Outline" del Eclipse (donde nos muestra todos los controles insertados hasta el momento):
Nuestro problema solo requiere dos controles de tipo RadioButton. Para borrarlo lo podemos hacer directamente del formulario seleccionndolo y presionando la tecla delete o seleccionndolo desde la ventana "Outline" y luego presionando la tecla delete
Ahora a los dos controles de tipo RadioButton definimos sus id (los llamaremos r1 y r2 respectivamente).
Cambiamos sus propiedades text por los textos "sumar" y "restar".
No olvidemos tambin cambiar los id de los controles EditText por et1 y et2 (igual que en el problema anterior)
Por ltimo agreguemos un botn y un TextView para mostrar el resultado Inicializamos las propiedades del botn con los valores:
i d : but t on1 t ext : oper ar
Y el tercer TextView con los valores:
i d : t v3 t ext : r esul t ado
Podemos controlar en la ventana "Outline" el id definido para cada control (tv1, et1, tv2, et2, radioGroup1, r1, r2, button1, tv3) Tambin podemos observar de que clase es cada control visual y el texto de la propiedad text para aquellos controles que tienen sentido su inicializacin.
Si nuestro problema requera ms de 3 RadioButton deberamos arrastrar dentro del RadioGroup otros controles de tipo RadioButton que se encuentran tambin en la pestaa de "Form Widgets"
Captura del evento clic del button e identifiacin del RadioButton seleccionado.
El cdigo fuente de la clase Proyecto003Activity es:
package andr oi d. pr oyect o003;
i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Radi oBut t on; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o003Act i vi t y ext ends Act i vi t y {
pr i vat e Edi t Text et 1, et 2; pr i vat e Text Vi ew t v3; pr i vat e Radi oBut t on r 1, r 2;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. et 2) ; t v3=( Text Vi ew) f i ndVi ewByI d( R. i d. t v3) ; r 1=( Radi oBut t on) f i ndVi ewByI d( R. i d. r 1) ; r 2=( Radi oBut t on) f i ndVi ewByI d( R. i d. r 2) ; }
/ / Est e mt odo se ej ecut ar cuando se pr esi one el bot n publ i c voi d oper ar ( Vi ew vi ew) { St r i ng val or 1=et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng val or 2=et 2. get Text ( ) . t oSt r i ng( ) ; i nt nr o1=I nt eger . par seI nt ( val or 1) ; i nt nr o2=I nt eger . par seI nt ( val or 2) ; i f ( r 1. i sChecked( ) ==t r ue) { i nt suma=nr o1+nr o2; St r i ng r esu=St r i ng. val ueOf ( suma) ; t v3. set Text ( r esu) ; } el se i f ( r 2. i sChecked( ) ==t r ue) { i nt r est a=nr o1- nr o2; St r i ng r esu=St r i ng. val ueOf ( r est a) ; t v3. set Text ( r esu) ; } }
}
Primero debemos enlazar el objeto button1 con el mtodo operar. Para esto similar al problema anterior seleccionamos el control button1 y cambiamos la propiedad OnClick por el valor operar (si no hacemos esto nunca se ejecutar el mtodo operar de la clase Proyecto003Activity) Como podemos ver el cdigo fuente es igual al problema anterior. Tenemos dos objetos ms que debemos inicializar en el mtodo onCreate:
r 1=( Radi oBut t on) f i ndVi ewByI d( R. i d. r 1) ; r 2=( Radi oBut t on) f i ndVi ewByI d( R. i d. r 2) ;
Las variables r1 y r2 son de la clase RadioButton y son necesarios en el mtodo operar para verificar cual de los dos RadioButton estn seleccionados. La clase RadioButton tiene un mtodo llamado isChecked que retorna true si dicho elemento est seleccionado:
publ i c voi d oper ar ( Vi ew vi ew) { St r i ng val or 1=et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng val or 2=et 2. get Text ( ) . t oSt r i ng( ) ; i nt nr o1=I nt eger . par seI nt ( val or 1) ; i nt nr o2=I nt eger . par seI nt ( val or 2) ; i f ( r 1. i sChecked( ) ==t r ue) { i nt suma=nr o1+nr o2; St r i ng r esu=St r i ng. val ueOf ( suma) ; t v3. set Text ( r esu) ; } el se i f ( r 2. i sChecked( ) ==t r ue) { i nt r est a=nr o1- nr o2; St r i ng r esu=St r i ng. val ueOf ( r est a) ; t v3. set Text ( r esu) ; } }
Final del proyecto003.
5 - Control CheckBox
El objetivo de este concepto es practicar lo visto hasta ahora e incorporar el control visual CheckBox
Problema: Realizar la carga de dos nmeros en controles de tipo EditText. Mostrar un mensaje que solicite la carga de los valores. Disponer dos controles de tipo CheckBox para seleccionar si queremos sumar y/o restar dichos valores. Finalmente mediante un control de tipo Button efectuamos la operacin respectiva. Mostramos el o los resultados en un TextView.
Lo nuevo en este problema es la insercin de dos objetos de la clase CheckBox que se encuentra en la pestaa "FormWidgets":
Luego la interfaz grfica final para este problema y los nombres de los controles los podemos ver en la ventana "Outline":
No olvidemos inicializar la propiedad OnClick del objeto button1 con el valor "operar" (es el nombre del mtodo a ejecutarse cuando se presione el botn y lo implementa la clase que hacemos)
Cdigo fuente: package andr oi d. pr oyect o004;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . CheckBox; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o004Act i vi t y ext ends Act i vi t y {
pr i vat e Edi t Text et 1, et 2; pr i vat e Text Vi ew t v3; pr i vat e CheckBox checkBox1, checkBox2;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. et 2) ; t v3=( Text Vi ew) f i ndVi ewByI d( R. i d. t v3) ; checkBox1=( CheckBox) f i ndVi ewByI d( R. i d. checkBox1) ; checkBox2=( CheckBox) f i ndVi ewByI d( R. i d. checkBox2) ; }
/ / Est e mt odo se ej ecut ar cuando se pr esi one el bot n publ i c voi d oper ar ( Vi ew vi ew) { St r i ng val or 1=et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng val or 2=et 2. get Text ( ) . t oSt r i ng( ) ; i nt nr o1=I nt eger . par seI nt ( val or 1) ; i nt nr o2=I nt eger . par seI nt ( val or 2) ; St r i ng r esu=" " ; i f ( checkBox1. i sChecked( ) ==t r ue) { i nt suma=nr o1+nr o2; r esu=" La suma es: " + suma; } i f ( checkBox2. i sChecked( ) ==t r ue) { i nt r est a=nr o1- nr o2; r esu=r esu + " La r est a es: " + r est a; } t v3. set Text ( r esu) ; } }
Definimos dos objetos de la clase CheckBox como atributos de la clase:
pr i vat e CheckBox checkBox1, checkBox2;
En el mtodo onCreate los inicializamos con los objetos definidos en el archivo XML:
checkBox1=( CheckBox) f i ndVi ewByI d( R. i d. checkBox1) ; checkBox2=( CheckBox) f i ndVi ewByI d( R. i d. checkBox2) ;
En el mtodo operar debemos definir dos if a la misma altura ya que los dos controles de tipo CheckBox pueden estar seleccionados simultaneamente. Definimos una variable de tipo String y la inicializamos con cadena vaca para el caso en que los dos CheckBox no estn seleccionados:
St r i ng r esu=" " ; i f ( checkBox1. i sChecked( ) ==t r ue) { i nt suma=nr o1+nr o2; r esu=" La suma es: " + suma; } i f ( checkBox2. i sChecked( ) ==t r ue) { i nt r est a=nr o1- nr o2; r esu=r esu + " La r est a es: " + r est a; } t v3. set Text ( r esu) ;
Final del proyecto004.
6 - Control Spinner
El objetivo de este concepto es practicar lo visto hasta ahora e incorporar el control visual Spinner
El control Spinner muestra una lista de String y nos permite seleccionar uno de ellos. Cuando se lo selecciona se abre y muestra todos sus elementos para permitir seleccionar uno de ellos.
Problema: Realizar la carga de dos nmeros en controles de tipo EditText. Mostrar un mensaje que solicite la carga de los valores. Disponer un control de tipo Spinner que permita seleccionar si queremos sumar, restar, multiplicar o dividir dichos valores. Finalmente mediante un control de tipo Button efectuamos la operacin respectiva. Mostramos el resultado en un TextView.
Lo nuevo en este problema es la insercin de un control de tipo Spinner que se encuentra en la pestaa "FormWidgets":
Definimos la propiedad id con el valor spinner1.
En la siguiente imagen en la ventana "Outline" de Eclipse podemos observar los objetos dispuestos en el formulario, sus Id, sus textos y de que clase son cada uno:
No olvidemos inicializar la propiedad OnClick del objeto button1 con el valor "operar" (dicho nombre es el mtodo que debemos implementar)
Cdigo fuente: package andr oi d. pr oyect o005;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Ar r ayAdapt er ; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Spi nner ; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o005Act i vi t y ext ends Act i vi t y { pr i vat e Spi nner spi nner 1; pr i vat e Edi t Text et 1, et 2; pr i vat e Text Vi ew t v3; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. et 2) ; t v3=( Text Vi ew) f i ndVi ewByI d( R. i d. t v3) ;
spi nner 1 = ( Spi nner ) f i ndVi ewByI d( R. i d. spi nner 1) ; St r i ng [ ] opci ones={" sumar " , " r est ar " , " mul t i pl i car " , " di vi di r " }; Ar r ayAdapt er <St r i ng> adapt er = new Ar r ayAdapt er <St r i ng>( t hi s, andr oi d. R. l ayout . si mpl e_spi nner _i t em, opci ones) ; spi nner 1. set Adapt er ( adapt er ) ; }
/ / Est e mt odo se ej ecut ar cuando se pr esi one el bot n publ i c voi d oper ar ( Vi ew vi ew) { St r i ng val or 1=et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng val or 2=et 2. get Text ( ) . t oSt r i ng( ) ; i nt nr o1=I nt eger . par seI nt ( val or 1) ; i nt nr o2=I nt eger . par seI nt ( val or 2) ; St r i ng sel ec=spi nner 1. get Sel ect edI t em( ) . t oSt r i ng( ) ; i f ( sel ec. equal s( " sumar " ) ) { i nt suma=nr o1+nr o2; St r i ng r esu=St r i ng. val ueOf ( suma) ; t v3. set Text ( r esu) ; } el se i f ( sel ec. equal s( " r est ar " ) ) { i nt r est a=nr o1- nr o2; St r i ng r esu=St r i ng. val ueOf ( r est a) ; t v3. set Text ( r esu) ; } el se i f ( sel ec. equal s( " mul t i pl i car " ) ) { i nt mul t i =nr o1*nr o2; St r i ng r esu=St r i ng. val ueOf ( mul t i ) ; t v3. set Text ( r esu) ;
} el se i f ( sel ec. equal s( " di vi di r " ) ) { i nt di vi =nr o1/ nr o2; St r i ng r esu=St r i ng. val ueOf ( di vi ) ; t v3. set Text ( r esu) ; } }
}
Definimos un objeto de la clase Spinner:
pr i vat e Spi nner spi nner 1;
En el mtodo onCreate obtenemos la referencia al control visual declarado en el archivo XML:
spi nner 1=( Spi nner ) f i ndVi ewByI d( R. i d. spi nner 1) ;
Definimos un vector con la lista de String que mostrar el Spinner: St r i ng [ ] opci ones={" sumar " , " r est ar " , " mul t i pl i car " , " di vi di r " };
Definimos y creamos un objeto de la clase ArrayAdapter::
Ar r ayAdapt er <St r i ng> adapt er = new Ar r ayAdapt er <St r i ng>( t hi s, andr oi d. R. l ayout . si mpl e_spi nner _i t em, opci ones) ;
Al constructor le pasamos como primer parmetro la referencia de nuestro Activity (this), el segundo parmetro indica el tipo de Spinner, pudiendo ser las constantes:
andr oi d. R. l ayout . si mpl e_spi nner _i t em andr oi d. R. l ayout . si mpl e_spi nner _dr opdown_i t em
El tercer parmetro es la referencia del vector que se mostrar: Luego llamamos al mtodo setAdapter de la clase Spinner pasando la referencia del objeto de la clase ArrayAdapter que acabamos de crear:
spi nner 1. set Adapt er ( adapt er ) ;
En el mtodo operar que se ejecuta cuando presionamos el botn procedemos a extraer el contenido seleccionado del control Spinner:
St r i ng sel ec=spi nner 1. get Sel ect edI t em( ) . t oSt r i ng( ) ;
Luego mediante una serie de if anidados verificamos si debemos sumar, restar, multiplicar o dividir:
i f ( sel ec. equal s( " sumar " ) ) { i nt suma=nr o1+nr o2; St r i ng r esu=St r i ng. val ueOf ( suma) ; t v3. set Text ( r esu) ; } el se i f ( sel ec. equal s( " r est ar " ) ) { i nt r est a=nr o1- nr o2; St r i ng r esu=St r i ng. val ueOf ( r est a) ; t v3. set Text ( r esu) ; } el se i f ( sel ec. equal s( " mul t i pl i car " ) ) { i nt mul t i =nr o1*nr o2; St r i ng r esu=St r i ng. val ueOf ( mul t i ) ; t v3. set Text ( r esu) ;
} el se i f ( sel ec. equal s( " di vi di r " ) ) { i nt di vi =nr o1/ nr o2; St r i ng r esu=St r i ng. val ueOf ( di vi ) ; t v3. set Text ( r esu) ; }
Final del proyecto005.
7 - Control ListView
El control ListView a diferencia del Spinner que se cierra luego de seleccionar un elemento permanecen visibles varios elementos (se lo utiliza cuando hay que mostrar muchos elementos)
Si la lista no entra en el espacio que hemos fijado para el ListView nos permite hacer scroll de los mismos.
El control ListView se encuentra en la pestaa "compositive".
Problema: Disponer un ListView con los nombres de paises de sudamrica. Cuando se seleccione un pas mostrar en un TextView la cantidad de habitantes del pas seleccionado.
La interfaz visual a implementar es la siguiente (primero disponemos un TextView (llamado tv1) y un ListView (llamado listView1)):
Cdigo fuente: package andr oi d. pr oyect o006;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Adapt er Vi ew; i mpor t andr oi d. wi dget . Adapt er Vi ew. OnI t emCl i ckLi st ener ; i mpor t andr oi d. wi dget . Ar r ayAdapt er ; i mpor t andr oi d. wi dget . Li st Vi ew; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o006Act i vi t y ext ends Act i vi t y { pr i vat e St r i ng[ ] pai ses={" Ar gent i na" , " Chi l e" , " Par aguay" , " Bol i vi a" , " Per u" ,
" Ecuador " , " Br asi l " , " Col ombi a" , " Venezuel a" , " Ur uguay" }; pr i vat e St r i ng[ ] habi t ant es={" 40000000" , " 17000000" , " 6500000" , " 10000000" , " 30000000" ,
" 14000000" , " 183000000" , " 44000000" , " 29000000" , " 3500000" }; pr i vat e Text Vi ew t v1; pr i vat e Li st Vi ew l v1; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
t v1=( Text Vi ew) f i ndVi ewByI d( R. i d. t v1) ; l v1 =( Li st Vi ew) f i ndVi ewByI d( R. i d. l i st Vi ew1) ; Ar r ayAdapt er <St r i ng> adapt er = new Ar r ayAdapt er <St r i ng>( t hi s, andr oi d. R. l ayout . si mpl e_l i st _i t em_1, pai ses) ; l v1. set Adapt er ( adapt er ) ; l v1. set OnI t emCl i ckLi st ener ( new OnI t emCl i ckLi st ener ( ) {
publ i c voi d onI t emCl i ck( Adapt er Vi ew<?> par ent , Vi ew v, i nt posi ci on, l ong i d) { t v1. set Text ( " Pobl aci n de " + l v1. get I t emAt Posi t i on( posi ci on) + " es " + habi t ant es[ posi ci on] ) ; } }) ; }
}
Primero definimos dos vectores paralelos donde almacenamos en uno los nombres de paises y en el otro almacenamos la cantidad de habitantes de dichos paises:
pr i vat e St r i ng[ ] pai ses={" Ar gent i na" , " Chi l e" , " Par aguay" , " Bol i vi a" , " Per u" ,
" Ecuador " , " Br asi l " , " Col ombi a" , " Venezuel a" , " Ur uguay" }; pr i vat e St r i ng[ ] habi t ant es={" 40000000" , " 17000000" , " 6500000" , " 10000000" , " 30000000" ,
Definimos un objeto de tipo TextView y otro de tipo ListView donde almacenaremos las referencias a los objetos que definimos en el archivo XML:
pr i vat e Text Vi ew t v1; pr i vat e Li st Vi ew l v1;
En el mtodo onCreate obtenemos la referencia a los dos objetos:
t v1=( Text Vi ew) f i ndVi ewByI d( R. i d. t v1) ; l v1 =( Li st Vi ew) f i ndVi ewByI d( R. i d. l i st Vi ew1) ;
Creamos un objeto de la clase ArrayAdapter de forma similar a como lo hicimos cuando vimos la clase Spinner:
Ar r ayAdapt er <St r i ng> adapt er = new Ar r ayAdapt er <St r i ng>( t hi s, andr oi d. R. l ayout . si mpl e_l i st _i t em_1, pai ses) ; l v1. set Adapt er ( adapt er ) ;
Llamamos al mtodo setOnItemClicListener de la clase ListView y le pasamos como parmetro una clase annima que implementa la interfaz OnItemClickListener (dicha interfaz define el mtodo onItemClick que se dispara cuando seleccionamos un elemento del ListView):
l v1. set OnI t emCl i ckLi st ener ( new OnI t emCl i ckLi st ener ( ) { @Over r i de publ i c voi d onI t emCl i ck( Adapt er Vi ew<?> par ent , Vi ew v, i nt posi ci on, l ong i d) { t v1. set Text ( " Pobl aci n de " + l v1. get I t emAt Posi t i on( posi ci on) + " es " + habi t ant es[ posi ci on] ) ; } }) ;
Dentro del mtodo onItemClick modificamos el contenido del TextView con el nombre del pas y la cantidad de habitantes de dicho pas. Este mtodo recibe en el tercer parmetro la posicin del item seleccionado del ListView.
Cuando ejecutamos el proyecto podemos ver una interfaz en el emulador similar a esta:
Final del proyecto006.
8 - Control ImageButton
Hemos visto la creacin de objetos de la clase Button, ahora veremos otra clase muy similar a la anterior llamada ImageButton que tiene la misma filosofa de manejo con la diferencia que puede mostrar una imagen en su superficie.
Problema: Disponer un objeto de la clase ImageButton que muestre una imagen de un telfono. Cuando se presione mostrar en un control TextView el mensaje "Llamando".
Primero crearemos un proyecto llamado proyecto007 y luego debemos buscar una imagen en formato png que represente un telefono de 50*50 pxeles.
Nombre del archivo: telefono.png Ahora copiamos el archivo a la carpeta de recursos de nuestro proyecto : res\drawable-mdpi Desde el Eclipse en la ventana "Package Explorer" navegamos hasta la carpeta res y entramos al directorio drawable-mdpi y vemos que todava no est el archivo que acabamos de copiar. Para que se actualice el proyecto presionamos el botn derecho del mouse sobre esta carpeta y seleccionamos la opcin "Refresh":
Vemos que se actualiz el contenido de la carpeta y aparece la imagen que copiamos previamente.
Ahora insertaremos el objeto de la clase ImageButton en el formulario de nuestra aplicacin. La clase ImageButton se encuentra en la pestaa "Image & Media":
Aparece un dilogo de donde seleccionamos el archivo telefono. Luego de esto podemos ver que la superficie del objeto de la clase ImageButton muestra la imagen que almacenamos previamente en la carpeta de res.
Si queremos cambiar el archivo a mostrar debemos modificar la propiedad src (aparece nuevamente el dilogo que nos permite seleccionar la imagen) Inicializamos la propiedad ID con el nombre bi1
Agreguemos un TextView a nuestra aplicacin y configuremos sus propiedades ID (con tv1) y text. Luego la interfaz visual debe ser similar a:
Cdigo fuente: package andr oi d. pr oyect o007;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o007Act i vi t y ext ends Act i vi t y { pr i vat e Text Vi ew t v1; pr i vat e I mageBut t on i b1; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
t v1=( Text Vi ew) f i ndVi ewByI d( R. i d. t v1) ; }
/ / Est e mt odo se ej ecut ar cuando se pr esi one el I mageBut t on publ i c voi d l l amar ( Vi ew vi ew) { t v1. set Text ( " Ll amando" ) ; } }
Definimos los dos atributos:
Text Vi ew t v1;
Enlazamos el control definido en el archivo XML y la variable de java:
t v1=( Text Vi ew) f i ndVi ewByI d( R. i d. t v1) ;
Implementamos el mtodo que se ejecutar cuando se presione el el objeto de la clase ImageButton:
publ i c voi d l l amar ( Vi ew vi ew) { t v1. set Text ( " Ll amando" ) ; }
No olvidemos inicializar la propiedad OnClick del objeto ib1 con el nombre del mtodo "llamar" (recordemos que esto lo hacemos presionando el botn derecho del mouse sobre la imagen del objeto de la clase ImageButton y desde la opcin properties accedemos a la propiedad OnClick)
Final del proyecto007.
Comentarios extras de este control. Cuando copiamos el archivo lo hicimos a la carpeta:
dr awabl e- mdpi
Pero vimos que hay otras dos carpetas con nombres similares:
dr awabl e- l dpi dr awabl e- hdpi
El objetivo de estas otras dos carpetas es guardar las mismas imgenes pero con una resolucin mayor si la guardamos en drawable-hdpi y con una resolucin menor al guardarla en drawable- ldpi.
Esto se hace si queremos que nuestra aplicacin sea ms flexible si se ejecuta en un celular, en un tablet, en un televisor etc.
Debemos tener en cuenta estos tamaos:
En l a car pet a r es/ dr awabl e- mdpi / ( guar damos l a i magen con el t amao or i gi nal )
En l a car pet a r es/ dr awabl e- l dpi / ( guar damos l a i magen con el t amao del 75%con r espect o al de l a car pet a dr awabl e- mdpi )
En l a car pet a r es/ dr awabl e- hdpi / ( guar damos l a i magen con el t amao del 150% con r espect o al de l a car pet a dr awabl e- mdpi )
9 - Lanzar un segundo " Activity"
Hasta ahora todos los programas han tenido una sola ventana (Activity)
Es muy comn que una aplicacin tenga ms de una ventana. Para implementar esto en Android debemos plantear una segunda clase que tambin herede de la clase Activity (tengamos en cuenta que cuando utilizamos el plugin de Eclipse para Android automticamente cuando creamos un proyecto nos crea el archivo XML y java de la primer Activity)
Vamos a ver en este concepto los pasos que debemos dar para crear otro Activity y como activarlo desde el Activity principal.
Problema: Confeccionar un programa que muestre en la ventana principal un botn que al ser presionado muestre otra ventana (Activity) mostrando un TextView con el nombre del programador de la aplicacin y un botn para cerrar la ventana.
1 - Primero creamos un nuevo proyecto que lo llamaremos proyecto008 y en la ventana principal creamos la siguiente interfaz:
Es decir que nosotros queremos que cuando se presione el botn "Acerca De" nos abra otra ventana (Activity) y nos muestre el nombre del programador.
2 - Ahora tenemos que crear el segundo Activity. Crearemos primero el archivo XML. Presionamos el botn derecho sobre la carpeta layout y seleccionaremos la opcin New -> Android XML File
Aqu tenemos que definir el nombre del archivo XML (debe estar en minsculas), lo llamaremos acercade:
Implementamos ahora la interfaz visual de esta segunda ventana (Activity) disponiendo un objeto de la clase TextView donde mostramos el nombre del autor de este programa y un Button para cerrar la ventana.
3 - Tenemos ahora que crear el archivo J ava donde dispondremos la funcionalidad de la segunda ventana (Activity)
Creamos una nueva clase al proyecto desde el men contextual(presionamos el botn derecho del mouse sobre el paquete android.proyecto008):
Al nombre de la clase la llamamos AcercaDe y debemos especificar que hereda de la clase Activity:
Ahora tenemos que modificar el archivo J ava generado con esto:
package andr oi d. pr oyect o008;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e;
publ i c cl ass Acer caDe ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . acer cade) ; } }
Como podemos ver la clase AcercaDe hereda de la clase Activity e implementa el mtodo onCreate para enlazar el archivo XML que creamos anteriormente.
4 - Otro paso fundamental es registrar el Activity en el archivo "AndroidManifest.xml" que se encuentra en la raiz principal del proyecto. Seleccionamos el archivo y activamos la pestaa : "Application", presionamos el botn "add" y seleccionamos "Activity":
Por ltimo seleccionamos en "Application Nodes" la actividad creada y definimos la propiedad Name con el nombre de la clase que la implementa (en nuestro caso se llama AcercaDe):
5 - Ahora implementaremos la funcionalidad en la actividad (Activity) principal para que se active la segunda ventana.
Inicializamos la propiedad OnClick del objeto de la clase Button con el valor "lanzar", este es el mtodo que se ejecutar cuando se presione.
El cdigo fuente de la actividad principal queda:
package andr oi d. pr oyect o008;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . I nt ent ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew;
publ i c cl ass Pr oyect o008Act i vi t y ext ends Act i vi t y {
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
}
publ i c voi d l anzar ( Vi ew vi ew) { I nt ent i = new I nt ent ( t hi s, Acer caDe. cl ass ) ; st ar t Act i vi t y( i ) ; } }
En el mtodo lanzar creamos un objeto de la clase Intent y le pasamos como parmetros la referencia del objeto de esta clase (this) y la referencia del otro Activity (Acerca.class). Llamamos posteriormente al mtodo startActivity pasando el objeto de la clase Intent (con esto ya tenemos en pantalla la ventana del segundo Activity:
publ i c voi d l anzar ( Vi ew vi ew) { I nt ent i = new I nt ent ( t hi s, Acer caDe. cl ass ) ; st ar t Act i vi t y( i ) ; }
Si ejecutamos el programa podemos ver que cuando presionamos el botn "Acerca De" aparece la segunda ventana donde se muestra el TextView con el valor "Autor de este programa: Diego" y un botn con el texto "Finalizar" (si presionamos este botn no sucede nada, esto debido a que no hemos asociado ningn evento a dicho botn).
6 - Debemos codificar el evento OnClick de la segunda actividad. Seleccionemos el botn "Finalizar" y definamos en la propiedad OnClick el nombre de mtodo que se ejecutar al presionarse el botn (en nuestro caso lo llamaremos finalizar"):
El cdigo fuente de la actividad AcercaDe queda:
package andr oi d. pr oyect o008;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew;
publ i c cl ass Acer caDe ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . acer cade) ; }
publ i c voi d cer r ar ( Vi ew vi ew) { f i ni sh( ) ; } } Cuando se presiona el botn finalizar llamando al mtodo finish() que tiene por objetivo liberar el espacio de memoria de esta actividad y pedir que se active la actividad anterior.
Ahora nuestro programa est funcionando completamente:
Primer Activity:
Segundo Activity:
Ahora ya tenemos el programa funcionando en forma completa.
Final del proyecto008.
Problema propuesto
Realizar un programa que contenga dos Activity. En el primero que solicite el ingreso de una clave (control Password) Si ingresa la clave "abc123" activar el segundo Activity mostrando en un TextView un mensaje de bienvenida (mostrar en un TextView si se ingrese la clave incorrecta). Llamar al proyecto: proyecto009.
En tiempo de ejecucin los dos Activity deben mostrarse algo similar a esto:
Final del proyecto009.
10 - Lanzar un segundo " Activity" y pasar parmetros.
Hemos visto en el concepto anterior que un programa puede tener ms de una ventana representando cada ventana con una clase que hereda de Activity.
Una situacin muy comn es que la primer ventana necesite enviar datos a la segunda para que a partir de estos proceda a efectuar una accin.
Problema: Confeccionar un programa que solicite el ingreso de una direccin de un sitio web y seguidamente abrir una segunda ventana que muestre dicha pgina.
Para resolver este problema utilizaremos el control visual WebView que nos permite mostrar el contenido de un sitio web.
Crearemos un nuevo proyecto llamado proyecto010 y lo almacenaremos en el package name: android.proyecto010. 1 - Nuestro primer Activity tendr la siguiente interfaz visual (ver controles y ID de los controles):
Tenemos un control de tipo TextView (tv1), otro de tipo EditText y finalmente otro de tipo Button (button1) debemos inicializar las propiedades de cada uno de estos tres objetos. El cdigo fuente de esta Activity es:
package andr oi d. pr oyect o010;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . I nt ent ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ;
publ i c cl ass Pr oyect o010Act i vi t y ext ends Act i vi t y { pr i vat e Edi t Text et 1;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ; }
publ i c voi d ej ecut ar ( Vi ew vi ew) { I nt ent i = new I nt ent ( t hi s, Act i vi dad2. cl ass ) ; i . put Ext r a( " di r ecci on" , et 1. get Text ( ) . t oSt r i ng( ) ) ; st ar t Act i vi t y( i ) ; } }
Como podemos ver la diferencia con el concepto anterior es que llamamos al mtodo putExtra de la clase Intent. Tiene dos parmetros de tipo String, en el primero indicamos el nombre del dato y en el segundo el valor del dato:
publ i c voi d ej ecut ar ( Vi ew vi ew) { I nt ent i = new I nt ent ( t hi s, Act i vi dad2. cl ass ) ; i . put Ext r a( " di r ecci on" , et 1. get Text ( ) . t oSt r i ng( ) ) ; st ar t Act i vi t y( i ) ; }
La segunda interfaz visual (recordemos que debemos presionar el botn derecho sobre la carpeta layout y seleccionar la opcin New ->Android XML File) la llamaremos actividad2.xml:
En esta interfaz disponemos primero un control de tipo Button (button1) y un objeto de la clase WebView (se encuentra en la pestaa "Composite") y lo dejamos con el ID por defecto llamado webView1
Tenemos que crear el archivo J ava donde dispondremos la funcionalidad de la segunda ventana (Activity) Creamos una nueva clase al proyecto desde el men contextual(presionamos el botn derecho del mouse sobre el paquete android.proyecto010) Al nombre de la clase la llamamos Actividad2 y debemos especificar que hereda de la clase Activity Ahora tenemos que modificar el archivo J ava generado con esto:
package andr oi d. pr oyect o010;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. webki t . WebVi ew;
publ i c cl ass Act i vi dad2 ext ends Act i vi t y {
pr i vat e WebVi ew webVi ew1;
@Over r i de publ i c voi d onCr eat e( Bundl e b) { super . onCr eat e( b) ; set Cont ent Vi ew( R. l ayout . act i vi dad2) ;
webVi ew1=( WebVi ew) f i ndVi ewByI d( R. i d. webVi ew1) ;
Bundl e bundl e=get I nt ent ( ) . get Ext r as( ) ; webVi ew1. l oadUr l ( " ht t p: / / " +bundl e. get St r i ng( " di r ecci on" ) ) ; }
publ i c voi d f i nal i zar ( Vi ew vi ew) { f i ni sh( ) ; } }
En esta clase definimos una variable de tipo Bundle y la inicializamos llamando al mtodo getExtras() de la clase Intent (esto lo hacemos para recuperar el o los parmetros que envi la otra actividad (Activity)):
Bundl e bundl e=get I nt ent ( ) . get Ext r as( ) ; webVi ew1. l oadUr l ( " ht t p: / / " +bundl e. get St r i ng( " di r ecci on" ) ) ;
El mtodo loadUrl de la clase WebView permite visualizar el contenido de un sitio web. Otro paso fundamental es registrar el Activity en el archivo "AndroidManifest.xml" que se encuentra en la raiz principal del proyecto.
Seleccionamos el archivo y activamos la pestaa : "Application", presionamos el botn "add" y seleccionamos "Activity".
Por ltimo seleccionamos en "Application Nodes" la actividad creada y definimos la propiedad Name con el nombre de la clase que la implementa (en nuestro caso se llama Actividad2)
Como nuestra aplicacin debe acceder a internet debemos hacer otra configuracin en el archivo "AndroidManifest.xml", debemos ir a la pestaa "Permissions" presionar el botn "Add" y seleccionar "Uses Permissions":
Luego fijar en la propiedad name el valor android.permission.INTERNET Ahora nuestro programa debera estar funcionando completamente.
La primer ventana debera ser algo similar a esto:
La segunda ventana debera ser algo similar a esto otro:
Final del proyecto010.
11 - Almacenamiento de datos mediante la clase SharedPreferences
Veremos que la plataforma de Android nos da varias facilidades para el almacenamiento permanente de datos (es decir que los mismos no se borran cuando se apaga la aplicacin)
Segn el tipo de necesidades utilizaremos alguno de estos mtodos:
1. Mediante la clase SharedPreferences. 2. Mediante archivos de Texto. 3. En una base de datos.
No ser raro que una aplicacin utilice ms de uno de estos mtodos para el almacenamiento de datos.
Cuando tenemos que almacenar una cantidad limitada de datos es adecuado utilizar la clase SharedPreferences. Por ejemplo configuraciones de la aplicacin como pueden ser colores de pantalla, nivel actual en un juego, datos iniciales de controles de entrada de dato etc.
Problema: Confeccionar un programa que solicite el ingrese del mail de una persona. Guardar el mail ingresado utilizando la clase SharedPreferences. Cada vez que se inicie la aplicacin almacenar en el control EditText el ltimo mail ingresado. Disponer un botn para almacenar el mail ingresado y finalizar el programa.
Crearemos un nuevo proyecto llamado proyecto011 y lo almacenaremos en el package name: android.proyecto011.
La interfaz visual a implementar y los Id de los controles visuales son los siguientes:
Es decir:
Di sponemos un Text Vi ew y def i ni mos su I D con el nombr e t v1 l a pr opi edad Text con " I ngr ese el mai l : " .
Di sponemos un Edi t Text y def i ni mos su I D con el nombr e et 1. Di sponemos un But t on y def i ni mos su pr opi edad I d con el nombr e but t on1 su pr opi edad Text con el val or conf i r mar su pr opi edad OnCl i c con el val or ej ecut ar
El cdigo java es: package andr oi d. pr oyect o011;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. cont ent . Shar edPr ef er ences; i mpor t andr oi d. cont ent . Shar edPr ef er ences. Edi t or ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ;
publ i c cl ass Pr oyect o011Act i vi t y ext ends Act i vi t y { pr i vat e Edi t Text et 1;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ;
Shar edPr ef er ences pr ef e=get Shar edPr ef er ences( " dat os" , Cont ext . MODE_PRI VATE) ; et 1. set Text ( pr ef e. get St r i ng( " mai l " , " " ) ) ; }
publ i c voi d ej ecut ar ( Vi ew v) { Shar edPr ef er ences pr ef er enci as=get Shar edPr ef er ences( " dat os" , Cont ext . MODE_PRI VATE) ; Edi t or edi t or =pr ef er enci as. edi t ( ) ; edi t or . put St r i ng( " mai l " , et 1. get Text ( ) . t oSt r i ng( ) ) ; edi t or . commi t ( ) ; f i ni sh( ) ; } }
Obtenemos la referencia del EditText:
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ;
Obtenemos una referencia de un objeto de la clase SharedPreferences a travs del mtodo getSharedPreferences. El primer parmetro es el nombre del archivo de preferencias y el segundo la forma de creacin del archivo (MODE_PRIVATE indica que solo esta aplicacin puede consultar el archivo XML que se crea)
Shar edPr ef er ences pr ef e=get Shar edPr ef er ences( " dat os" , Cont ext . MODE_PRI VATE) ;
Para extraer los datos del archivo de preferencias debemos indicar el nombre a extraer y un valor de retorno si dicho nombre no existe en el archivo de preferencias (en nuestro ejemplo la primera vez que se ejecute nuestro programa como es lgico no existe el archivo de preferencias lo que hace que Android lo cree, si tratamos de extraer el valor de mail retornar el segundo parmetro es decir el String con una cadena vaca:
et 1. set Text ( pr ef e. get St r i ng( " mai l " , " " ) ) ;
Cuando se presiona el botn "Confirmar" lo que hacemos es grabar en el archivo de preferencias el contenido del EditText en una variable llamada "mail":
publ i c voi d ej ecut ar ( Vi ew v) { Shar edPr ef er ences pr ef er enci as=get Shar edPr ef er ences( " dat os" , Cont ext . MODE_PRI VATE) ; Edi t or edi t or =pr ef er enci as. edi t ( ) ; edi t or . put St r i ng( " mai l " , et 1. get Text ( ) . t oSt r i ng( ) ) ; edi t or . commi t ( ) ; f i ni sh( ) ; }
Debemos crear un objeto de la clase Editor y obtener la referencia del objeto de la clase SharedPreferences que acabamos de crear. Mediante el mtodo putString almacenamos en mail el valor del String cargado en el EditText. Luego debemos llamar al mtodo commit de la clase editor para que el dato quede almacenado en forma permanente en el archivo de preferencias. Esto hace que cuando volvamos a arrancar la aplicacin se recupere el ltimo mail ingresado.
Recordemos que el mtodo finish de la clase Activity finaliza la actividad actual (como tenemos una aplicacin con una sola actividad finalizar completamente nuestro programa.
Final del proyecto011.
Comentarios extras. El modo de operacin del archivo puede ser:
MODE_PRI VATE sol o l a apl i caci n puede acceder al ar chi vo de pr ef er enci as.
MODE_WORLD_READABLE ot r as apl i caci ones pueden consul t ar el ar chi vo de pr ef er enci as
MODE_WORLD_WRI TEABLE ot r as apl i caci ones pueden consul t ar y modi f i car el ar chi vo.
MODE_MULTI _PROCESS var i os pr ocesos pueden acceder ( Requi er e Andr oi d 2. 3)
Cuando guardamos datos en el archivo de preferencias podemos almacenar distintos tipos de datos segn el mtodo que llamemos en el momento de grabar:
edi t or . put I nt ( " edad" , 3) ; edi t or . put Bool ean( " act i vo" , t r ue) ; edi t or . put Fl oat ( " al t ur a" , 2. 3f ) ;
Cuando los recuperamos debemos indicar tambin que tipo de datos extraemos:
i nt e=pr ef e. get I nt ( " edad" , 0) ; bool ean act i =pr ef e. get Bool ean( " act i vo" , f al se) ; f l oat al t =pr ef e. get Fl oat ( " al t ur a" , 0f ) ;
Problema propuesto
Realizar un programa que genere un nmero aleatorio entre 1 y 50, pedir que el operador lo adivine, informar si gan o si el nmero es mayor o menor al ingresado. Cuando el operador lo adivine incrementar en uno el puntaje de juego. Cada vez que se ingrese a la aplicacin mostrar el puntaje actual, es decir recordar el puntaje en un archivo de preferencias.
La interfaz visual de la aplicacin a desarrollar es:
Final del proyecto012.
12 - Almacenamiento de datos en un archivo de texto en la memoria interna.
Otra posibilidad de almacenar datos en nuestro dispositivo Android es el empleo de un archivo de texto que se almacenar en el almacenamiento interno del equipo (la otro posibilidad es almacenarlo en una tarjeta SD Card)
Problema: Confeccionar un programa que permita almacenar notas en un control EditText y cuando se presione un botn almacenar los datos del EditText en un archivo de texto llamado "notas.txt".
Cada vez que se ingrese al programa verificar si existe el archivo de textos "notas.txt" proceder a su lectura y almacenamiento de datos en el EditText.
Crear un proyecto en Eclipse de tipo "Android Project" y definir como nombre: proyecto013 y localizarlo en el paquete android.proyecto013.
La interfaz visual, los controles y sus ID son los siguientes:
El cdigo fuente de la aplicacin: package andr oi d. pr oyect o013;
i mpor t j ava. i o. Buf f er edReader ; i mpor t j ava. i o. I OExcept i on; i mpor t j ava. i o. I nput St r eamReader ; i mpor t j ava. i o. Out put St r eamWr i t er ;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass Pr oyect o013Act i vi t y ext ends Act i vi t y { pr i vat e Edi t Text et 1; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. et 1) ; St r i ng [ ] ar chi vos=f i l eLi st ( ) ;
i f ( exi st e( ar chi vos, " not as. t xt " ) ) t r y { I nput St r eamReader ar chi vo=new I nput St r eamReader ( openFi l eI nput ( " not as. t xt " ) ) ; Buf f er edReader br =new Buf f er edReader ( ar chi vo) ; St r i ng l i nea=br . r eadLi ne( ) ; St r i ng t odo=" " ; whi l e ( l i nea! =nul l ) { t odo=t odo+l i nea+" \ n" ; l i nea=br . r eadLi ne( ) ; } br . cl ose( ) ; ar chi vo. cl ose( ) ; et 1. set Text ( t odo) ; } cat ch ( I OExcept i on e) { } }
pr i vat e bool ean exi st e( St r i ng[ ] ar chi vos, St r i ng ar chbusca) { f or ( i nt f =0; f <ar chi vos. l engt h; f ++) i f ( ar chbusca. equal s( ar chi vos[ f ] ) ) r et ur n t r ue; r et ur n f al se; }
publ i c voi d gr abar ( Vi ew v) { t r y { Out put St r eamWr i t er ar chi vo = new Out put St r eamWr i t er ( openFi l eOut put ( " not as. t xt " , Act i vi t y. MODE_PRI VATE) ) ; ar chi vo. wr i t e( et 1. get Text ( ) . t oSt r i ng( ) ) ; ar chi vo. f l ush( ) ; ar chi vo. cl ose( ) ; }cat ch ( I OExcept i on e) { } Toast t =Toast . makeText ( t hi s, " Los dat os f uer on gr abados" , Toast . LENGTH_SHORT) ; t . show( ) ; f i ni sh( ) ; } }
Veamos primero como grabamos datos en un archivo de texto. Esto se hace en el mtodo grabar que se ejecuta cuando presionamos el botn "grabar" (recordemos de inicializar la propiedad "OnClick" del botn):
publ i c voi d gr abar ( Vi ew v) { t r y { Out put St r eamWr i t er ar chi vo = new Out put St r eamWr i t er ( openFi l eOut put ( " not as. t xt " , Act i vi t y. MODE_PRI VATE) ) ;
Creamos un objeto de la clase OutputStreamWriter y al constructor de dicha clase le enviamos el dato que retorna el mtodo openFileOutput propio de la clase Activity que le pasamos como parmetro el nombre del archivo de texto y el modo de apertura.
Seguidamente si el archivo se cre correctamente procedemos a llamar al mtodo write y le pasamos el String a grabar, en este caso extraemos los datos del EditText:
ar chi vo. wr i t e( et 1. get Text ( ) . t oSt r i ng( ) ) ;
Luego de grabar con el mtodo write llamamos al mtodo flush para que vuelque todos los datos que pueden haber quedado en el buffer y procedemos al cerrado del archivo:
ar chi vo. f l ush( ) ; ar chi vo. cl ose( ) ;
Todo esto est cerrado en un try/catch para verificar si sucede algn error en la apertura del archivo. Finalmente mostramos un mensaje temporal en pantalla utilizando la clase Toast:
Toast t =Toast . makeText ( t hi s, " Los dat os f uer on gr abados" , Toast . LENGTH_SHORT) ; t . show( ) ; f i ni sh( ) ;
Para crear un objeto de la clase Toast llamamos al mtodo makeText de la clase Toast y le pasamos la referencia del Activity actual, el String a mostrar y el tiempo de duracin del mensaje. Con el objeto devuelto por el mtodo makeText procedemos a llamar seguidamente al mtodo show para que se muestre el mensaje.
Es comn llamar al mtodo show de la clase Toast en una sola lnea como esta:
Toast . makeText ( t hi s, " Los dat os f uer on gr abados" , Toast . LENGTH_SHORT) . show( ) ;
El mtodo onCreate tiene por objetivo verificar si existe el archivo de texto, proceder a su lectura y mostrar su contenido en el EditText.
Primero obtenemos la lista de todos los archivos creados por la Activity. En nuestro ejemplo puede ser cero o uno:
St r i ng [ ] ar chi vos=f i l eLi st ( ) ;
Llamamos a un mtodo que verifica si en el vector de tipo String existe el archivo "notas.txt":
i f ( exi st e( ar chi vos, " not as. t xt " ) )
En el caso que me retorne true procedemos a crear un objeto de la clase InputStreamReader y al constructor de dicha clase le pasamos el dato devuelto por el mtodo openFileInput:
I nput St r eamReader ar chi vo=new I nput St r eamReader ( openFi l eI nput ( " not as. t xt " ) ) ;
Creamos un objeto de la clase BufferedReader y le pasamos al constructor la referencia del objeto de la clase InputStreamReader:
Buf f er edReader br =new Buf f er edReader ( ar chi vo) ;
Leemos la primer lnea del archivo de texto:
St r i ng l i nea=br . r eadLi ne( ) ;
Inicializamos un String vaco:
St r i ng t odo=" " ;
Mientras el mtodo readLine de la clase BufferedReader devuelva un String:
whi l e ( l i nea! =nul l ) {
Lo concatenamos al String junto a un salto de lnea:
t odo=t odo+l i nea+" \ n" ;
Leemos la prxima lnea:
l i nea=br . r eadLi ne( ) ; }
Llamamos al mtodo close de la clase BufferedReader y al del InputStreamReader:
br . cl ose( ) ; ar chi vo. cl ose( ) ;
Cargamos el EditText con el contenido del String que contiene todos los datos del archivo de texto:
et 1. set Text ( t odo) ;
El mtodo existe llega un vector de tipo String y otro String a buscar. Dentro de un for verificamos el String a buscar con cada uno de los String del vector, si lo encontramos retornamos true. Si recorre todo el for sin encontrarlo fuera del for retornamos false:
pr i vat e bool ean exi st e( St r i ng[ ] ar chi vos, St r i ng ar chbusca) { f or ( i nt f =0; f <ar chi vos. l engt h; f ++) i f ( ar chbusca. equal s( ar chi vos[ f ] ) ) r et ur n t r ue; r et ur n f al se; }
Final del proyecto013.
13 - Almacenamiento de datos en un archivo de texto localizado en una tarjeta SD
En el concepto anterior vimos como crear y leer un archivo de texto en la memoria interna del equipo Android. En algunas situaciones podra ser til almacenar los datos en una tarjeta SD, esto debido a su mayor capacidad o la facilidad de compartir los archivos con otras personas entregando la tarjeta SD.
Problema: Confeccionar un programa que permita ingresar el nombre de un archivo y el contenido. Permitir grabar los datos ingresados al presionar un botn. Disponer un segundo botn que permita recuperar los datos del archivo de texto.
Hacer que los archivos se graben en una tarjeta SD.
La interfaz visual a implementar es la siguiente:
El primer paso es modificar el archivo AndroidManifest.xml para permitir el acceso a la tarjeta SD desde nuestra aplicacin esto lo hacemos desde el editor visual del archivo AndroidManifest.xml:
Debemos presionar el botn "Add" seleccionar "Uses Permision" y luego en name seleccionar "android.permission.WRITE_EXTERNAL_STORAGE".
El cdigo fuente es: package andr oi d. pr oyect o014;
i mpor t j ava. i o. Buf f er edReader ; i mpor t j ava. i o. Fi l e; i mpor t j ava. i o. Fi l eI nput St r eam; i mpor t j ava. i o. Fi l eOut put St r eam; i mpor t j ava. i o. I OExcept i on; i mpor t j ava. i o. I nput St r eamReader ; i mpor t j ava. i o. Out put St r eamWr i t er ;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. os. Envi r onment ; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass Pr oyect o014Act i vi t y ext ends Act i vi t y { Edi t Text et 1; Edi t Text et 2;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 2) ; }
publ i c voi d gr abar ( Vi ew v) { St r i ng nomar chi vo = et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng cont eni do=et 2. get Text ( ) . t oSt r i ng( ) ; t r y { Fi l e t ar j et a = Envi r onment . get Ext er nal St or ageDi r ect or y( ) ; Fi l e f i l e = new Fi l e( t ar j et a. get Absol ut ePat h( ) , nomar chi vo) ; Out put St r eamWr i t er osw =new Out put St r eamWr i t er ( new Fi l eOut put St r eam( f i l e) ) ; osw. wr i t e( cont eni do) ; osw. f l ush( ) ; osw. cl ose( ) ; Toast . makeText ( t hi s, " Los dat os f uer on gr abados cor r ect ament e" , Toast . LENGTH_SHORT) . show( ) ; et 1. set Text ( " " ) ; et 2. set Text ( " " ) ; } cat ch ( I OExcept i on i oe) { } }
publ i c voi d r ecuper ar ( Vi ew v) { St r i ng nomar chi vo = et 1. get Text ( ) . t oSt r i ng( ) ; Fi l e t ar j et a = Envi r onment . get Ext er nal St or ageDi r ect or y( ) ; Fi l e f i l e = new Fi l e( t ar j et a. get Absol ut ePat h( ) , nomar chi vo) ; t r y { Fi l eI nput St r eamf I n = new Fi l eI nput St r eam( f i l e) ; I nput St r eamReader ar chi vo=new I nput St r eamReader ( f I n) ; Buf f er edReader br =new Buf f er edReader ( ar chi vo) ; St r i ng l i nea=br . r eadLi ne( ) ; St r i ng t odo=" " ; whi l e ( l i nea! =nul l ) { t odo=t odo+l i nea+" \ n" ; l i nea=br . r eadLi ne( ) ; } br . cl ose( ) ; ar chi vo. cl ose( ) ; et 2. set Text ( t odo) ;
} cat ch ( I OExcept i on e) { } }
}
El mtodo para grabar los datos en un archivo de texto localizado en una tarjeta SD comienza obteniendo el directorio raiz de la tarjeta a travs del mtodo getExternalStorageDirectory(), el mismo retorna un objeto de la clase File.
publ i c voi d gr abar ( Vi ew v) { St r i ng nomar chi vo = et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng cont eni do=et 2. get Text ( ) . t oSt r i ng( ) ; t r y { Fi l e t ar j et a = Envi r onment . get Ext er nal St or ageDi r ect or y( ) ;
Creamos un nuevo objeto de la clase File indicando el camino de la unidad SD y el nombre del archivo a crear:
Fi l e f i l e = new Fi l e( t ar j et a. get Absol ut ePat h( ) , nomar chi vo) ;
Por ltimo similar al acceso de un archivo interno creamos un objeto de la clase OutputStreamWriter:
Out put St r eamWr i t er osw =new Out put St r eamWr i t er ( new Fi l eOut put St r eam( f i l e) ) ;
Grabamos el contenido del EditText:
osw. wr i t e( cont eni do) ;
Cerramos el archivo:
osw. f l ush( ) ; osw. cl ose( ) ; Toast . makeText ( t hi s, " Los dat os f uer on gr abados cor r ect ament e" , Toast . LENGTH_SHORT) . show( ) ; et 1. set Text ( " " ) ; et 2. set Text ( " " ) ; } cat ch ( I OExcept i on i oe) { } }
Para la lectura del archivo nuevamente obtenemos la referencia de la tarjeta SD para obtener el path de la unidad de almacenamiento, el resto del algoritmo es similar al visto con un archivo interno:
publ i c voi d r ecuper ar ( Vi ew v) { St r i ng nomar chi vo = et 1. get Text ( ) . t oSt r i ng( ) ; Fi l e t ar j et a = Envi r onment . get Ext er nal St or ageDi r ect or y( ) ; Fi l e f i l e = new Fi l e( t ar j et a. get Absol ut ePat h( ) , nomar chi vo) ; t r y { Fi l eI nput St r eamf I n = new Fi l eI nput St r eam( f i l e) ; I nput St r eamReader ar chi vo=new I nput St r eamReader ( f I n) ; Buf f er edReader br =new Buf f er edReader ( ar chi vo) ; St r i ng l i nea=br . r eadLi ne( ) ; St r i ng t odo=" " ; whi l e ( l i nea! =nul l ) { t odo=t odo+l i nea+" \ n" ; l i nea=br . r eadLi ne( ) ; } br . cl ose( ) ; ar chi vo. cl ose( ) ; et 2. set Text ( t odo) ;
} cat ch ( I OExcept i on e) { } } Final del proyecto014.
14 - Almacenamiento en una base de datos SQLite
Hemos visto hasta ahora dos modos de almacenar datos en forma permanente (archivos de texto y la clase SharedPreferences), ahora veremos otra herramienta nativa de Android para almacenar datos en una base de datos llamada SQLite.
SQLite es una base de datos Open Source, es muy popular en muchos dispositivos pequeos, como Android.
Las ventajas que presenta utilizar SQLite es que no requiere configuracin, no tiene un servidor de base de datos ejecutndose en un proceso separado y es relativamente simple su empleo.
Problema: Confeccionar un programa que permita almacenar los datos de votantes de una eleccin. Crear la tabla votantes y definir los campos dni (documento de identidad), nombre del votante, colegio donde vota y nmero de mesa donde vota.
El programa debe permitir:
1 - Car ga de per sonas. 2 - Consul t a por el dni ( par a saber donde vot a) 3 - Bor r ado de per sonas 4 - Modi f i caci n de dat os.
Primero implementamos una interfaz visual similar a esta:
Lo primero que haremos es crear una clase que herede de SQLiteOpenHelper. Esta clase nos permite crear la base de datos y actualizar la estructura de tablas y datos iniciales.
Debemos implementar el constructor y sobreescribir los mtodos onCreate y onUpgrade.
El mtodo onCreate se le llama cuando la base de datos se crea por primera vez. Aqu es donde se define la estructura de las tablas y se cargan eventualmente los datos iniciales
En el mtodo onUpgrade se llama cuando la base de datos debe ser actualizada. Tiene por objetivo eliminar tablas, aadir tablas, o hacer cualquier otra cosa que necesita para actualizarse.
En nuestro problema implementaremos una nueva clase llamada AdminSQLiteOpenHelper que herede de la clase SQLiteOpenHelper: package andr oi d. pr oyect o015;
i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. dat abase. sql i t e. SQLi t eDat abase; i mpor t andr oi d. dat abase. sql i t e. SQLi t eDat abase. Cur sor Fact or y; i mpor t andr oi d. dat abase. sql i t e. SQLi t eOpenHel per ;
publ i c cl ass Admi nSQLi t eOpenHel per ext ends SQLi t eOpenHel per {
publ i c Admi nSQLi t eOpenHel per ( Cont ext cont ext , St r i ng nombr e, Cur sor Fact or y f act or y, i nt ver si on) { super ( cont ext , nombr e, f act or y, ver si on) ; }
@Over r i de publ i c voi d onCr eat e( SQLi t eDat abase db) { db. execSQL( " cr eat e t abl e vot ant es( dni i nt eger pr i mar y key, nombr e t ext , col egi o t ext , nr omesa i nt eger ) " ) ; }
@Over r i de publ i c voi d onUpgr ade( SQLi t eDat abase db, i nt ver si onAnt e, i nt ver si onNue) { db. execSQL( " dr op t abl e i f exi st s vot ant es" ) ; db. execSQL( " cr eat e t abl e vot ant es( dni i nt eger pr i mar y key, nombr e t ext , col egi o t ext , nr omesa i nt eger ) " ) ; } }
En el constructor solo llamamos al constructor de la clase padre pasando los datos que llegan en los parmetros:
publ i c Admi nSQLi t eOpenHel per ( Cont ext cont ext , St r i ng nombr e, Cur sor Fact or y f act or y, i nt ver si on) { super ( cont ext , nombr e, f act or y, ver si on) ; }
En el mtodo onCreate procedemos a crear la tabla votantes con los cuatro campos respectivos y definiendo el campo dni como primary key:
publ i c voi d onCr eat e( SQLi t eDat abase db) { db. execSQL( " cr eat e t abl e vot ant es( dni i nt eger pr i mar y key, nombr e t ext , col egi o t ext , nr omesa i nt eger ) " ) ; }
En el mtodo onUpgrade procedemos a borrar la tabla votantes y crear nuevamente la tabla (en este caso con la misma estructura pero podra ser otra en un caso ms real:
publ i c voi d onUpgr ade( SQLi t eDat abase db, i nt ver si onAnt e, i nt ver si onNue) { db. execSQL( " dr op t abl e i f exi st s vot ant es" ) ; db. execSQL( " cr eat e t abl e vot ant es( dni i nt eger pr i mar y key, nombr e t ext , col egi o t ext , nr omesa i nt eger ) " ) ; }
Ahora veamos la otra clase que implementar las altas, bajas, modificaciones y consultas: package andr oi d. pr oyect o015;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ent Val ues; i mpor t andr oi d. dat abase. Cur sor ; i mpor t andr oi d. dat abase. sql i t e. SQLi t eDat abase; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass Pr oyect o015Act i vi t y ext ends Act i vi t y { pr i vat e Edi t Text et 1, et 2, et 3, et 4; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 2) ; et 3=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 3) ; et 4=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 4) ; }
publ i c voi d al t a( Vi ew v) { Admi nSQLi t eOpenHel per admi n=new Admi nSQLi t eOpenHel per ( t hi s, " admi ni st r aci on" , nul l , 1) ; SQLi t eDat abase bd=admi n. get Wr i t abl eDat abase( ) ; St r i ng dni =et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng nombr e=et 2. get Text ( ) . t oSt r i ng( ) ; St r i ng col egi o=et 3. get Text ( ) . t oSt r i ng( ) ; St r i ng nr omesa=et 4. get Text ( ) . t oSt r i ng( ) ; Cont ent Val ues r egi st r o=new Cont ent Val ues( ) ; r egi st r o. put ( " dni " , dni ) ; r egi st r o. put ( " nombr e" , nombr e ) ; r egi st r o. put ( " col egi o" , col egi o ) ; r egi st r o. put ( " nr omesa" , nr omesa ) ; bd. i nser t ( " vot ant es" , nul l , r egi st r o) ; bd. cl ose( ) ; et 1. set Text ( " " ) ; et 2. set Text ( " " ) ; et 3. set Text ( " " ) ; et 4. set Text ( " " ) ; Toast . makeText ( t hi s, " Se car gar on l os dat os de l a per sona" , Toast . LENGTH_SHORT) . show( ) ; }
publ i c voi d consul t a( Vi ew v) { Admi nSQLi t eOpenHel per admi n=new Admi nSQLi t eOpenHel per ( t hi s, " admi ni st r aci on" , nul l , 1) ; SQLi t eDat abase bd=admi n. get Wr i t abl eDat abase( ) ; St r i ng dni =et 1. get Text ( ) . t oSt r i ng( ) ; Cur sor f i l a=bd. r awQuer y( " sel ect nombr e, col egi o, nr omesa f r om vot ant es wher e dni =" +dni +" " , nul l ) ; i f ( f i l a. moveToFi r st ( ) ) { et 2. set Text ( f i l a. get St r i ng( 0) ) ; et 3. set Text ( f i l a. get St r i ng( 1) ) ; et 4. set Text ( f i l a. get St r i ng( 2) ) ; } el se Toast . makeText ( t hi s, " No exi st e una per sona con di cho dni " , Toast . LENGTH_SHORT) . show( ) ; bd. cl ose( ) ;
}
publ i c voi d baj a( Vi ew v) { Admi nSQLi t eOpenHel per admi n=new Admi nSQLi t eOpenHel per ( t hi s, " admi ni st r aci on" , nul l , 1) ; SQLi t eDat abase bd=admi n. get Wr i t abl eDat abase( ) ; St r i ng dni =et 1. get Text ( ) . t oSt r i ng( ) ; i nt cant =bd. del et e( " vot ant es" , " dni =" +dni +" " , nul l ) ; bd. cl ose( ) ; et 1. set Text ( " " ) ; et 2. set Text ( " " ) ; et 3. set Text ( " " ) ; et 4. set Text ( " " ) ; i f ( cant ==1) Toast . makeText ( t hi s, " Se bor r l a per sona con di cho document o" , Toast . LENGTH_SHORT) . show( ) ; el se Toast . makeText ( t hi s, " No exi st e una per sona con di cho document o" , Toast . LENGTH_SHORT) . show( ) ; }
publ i c voi d modi f i caci on( Vi ew v) { Admi nSQLi t eOpenHel per admi n=new Admi nSQLi t eOpenHel per ( t hi s, " admi ni st r aci on" , nul l , 1) ; SQLi t eDat abase bd=admi n. get Wr i t abl eDat abase( ) ; St r i ng dni =et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng nombr e=et 2. get Text ( ) . t oSt r i ng( ) ; St r i ng col egi o=et 3. get Text ( ) . t oSt r i ng( ) ; St r i ng nr omesa=et 4. get Text ( ) . t oSt r i ng( ) ; Cont ent Val ues r egi st r o=new Cont ent Val ues( ) ; r egi st r o. put ( " nombr e" , nombr e) ; r egi st r o. put ( " col egi o" , col egi o) ; r egi st r o. put ( " nr omesa" , nr omesa) ; i nt cant = bd. updat e( " vot ant es" , r egi st r o, " dni =" +dni , nul l ) ; bd. cl ose( ) ; i f ( cant ==1) Toast . makeText ( t hi s, " se modi f i car on l os dat os" , Toast . LENGTH_SHORT) . show( ) ; el se Toast . makeText ( t hi s, " no exi st e una per sona con di cho document o" , Toast . LENGTH_SHORT) . show( ) ; } }
Como en problemas anteriores definimos los cuatro EditText como atributos y en el mtodo onCreate obtenemos la referencia de los mismos:
publ i c cl ass Pr oyect o015Act i vi t y ext ends Act i vi t y { pr i vat e Edi t Text et 1, et 2, et 3, et 4; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 2) ; et 3=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 3) ; et 4=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 4) ; }
1 - Alta de datos. Cuando se presiona el botn alta se ejecuta el mtodo "alta" recordemos inicializar la propiedad "OnClick" del botn desde la ventana de visualizacin del archivo XML.
Lo primero que hacemos en este mtodo es crear un objeto de la clase que planteamos anteriormente y le pasamos al constructor this (referencia del Activity actual), "administracion" (es el nombre de la base de datos que crearemos en el caso que no exista) luego pasamos null y un uno indicando que es la primer versin de la base de datos (en caso que cambiemos la estructura o agreguemos tablas por ejemplo podemos pasar un dos en lugar de un uno para que se ejecute el mtodo onUpgrade donde indicamos la nuestra estructura de la base de datos)
Luego de crear un objeto de la clase AdminSqLiteOpenHelper procedemos a crear un objeto de la clase SQLiteDataBase llamando al mtodo getWritableDatabase (la base de datos se abre en modo lectura y escritura).
Creamos un objeto de la clase ContentValues y mediante el mtodo put inicializamos todos tos campos a cargar.
Seguidamente llamamos al mtodo insert de la clase SQLiteDatabase pasando en el primer parmetro el nombre de la tabla, como segundo parmetro un null y por ltimo el objeto de la clase ContentValues ya inicializado (este mtodo es el que provoca que se inserte una nueva fila en la tabla votantes en la base de datos llamada administracion)
Borramos seguidamente los EditText y mostramos un mensaje para que conozca el operador que el alta de datos se efectu en forma correcta:
publ i c voi d al t a( Vi ew v) { Admi nSQLi t eOpenHel per admi n=new Admi nSQLi t eOpenHel per ( t hi s, " admi ni st r aci on" , nul l , 1) ; SQLi t eDat abase bd=admi n. get Wr i t abl eDat abase( ) ; St r i ng dni =et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng nombr e=et 2. get Text ( ) . t oSt r i ng( ) ; St r i ng col egi o=et 3. get Text ( ) . t oSt r i ng( ) ; St r i ng nr omesa=et 4. get Text ( ) . t oSt r i ng( ) ; Cont ent Val ues r egi st r o=new Cont ent Val ues( ) ; r egi st r o. put ( " dni " , dni ) ; r egi st r o. put ( " nombr e" , nombr e ) ; r egi st r o. put ( " col egi o" , col egi o ) ; r egi st r o. put ( " nr omesa" , nr omesa ) ; bd. i nser t ( " vot ant es" , nul l , r egi st r o) ; bd. cl ose( ) ; et 1. set Text ( " " ) ; et 2. set Text ( " " ) ; et 3. set Text ( " " ) ; et 4. set Text ( " " ) ; Toast . makeText ( t hi s, " Se car gar on l os dat os de l a per sona" , Toast . LENGTH_SHORT) . show( ) ; }
2 - Consulta de datos. Cuando se presiona el botn "Consulta por DNI" se ejecuta el mtodo consulta:
publ i c voi d consul t a( Vi ew v) { Admi nSQLi t eOpenHel per admi n=new Admi nSQLi t eOpenHel per ( t hi s, " admi ni st r aci on" , nul l , 1) ; SQLi t eDat abase bd=admi n. get Wr i t abl eDat abase( ) ; St r i ng dni =et 1. get Text ( ) . t oSt r i ng( ) ; Cur sor f i l a=bd. r awQuer y( " sel ect nombr e, col egi o, nr omesa f r om vot ant es wher e dni =" +dni +" " , nul l ) ; i f ( f i l a. moveToFi r st ( ) ) { et 2. set Text ( f i l a. get St r i ng( 0) ) ; et 3. set Text ( f i l a. get St r i ng( 1) ) ; et 4. set Text ( f i l a. get St r i ng( 2) ) ; } el se Toast . makeText ( t hi s, " No exi st e una per sona con di cho dni " , Toast . LENGTH_SHORT) . show( ) ; bd. cl ose( ) ;
}
En el mtodo consulta lo primero que hacemos es crear un objeto de la clase AdminSQLiteOpenHelper y obtener una referencia de la base de datos llamando al mtodo getWritableDatabase.
Seguidamente definimos una variable de la clase Cursor y la inicializamos con el valor devuelto por el mtodo llamado rawQuery.
La clase Cursos almacena en este caso una fila o cero filas (una en caso que hayamos ingresado un dni existente en la tabla votantes), llamamos al mtodo moveToFirst() de la clase Cursos y retorna true en caso de existir una persona con el dni ingresado, en caso contrario retorna cero.
Para recuperar los datos propiamente dichos que queremos consultar llamamos al mtodo getString y le pasamos la posicin del campo a recuperar (comienza a numerarse en cero, en este ejemplo la columna cero representa el campo nombre, la columna 1 representa el campo colegio y la columna 2 representa el campo nromesa)
3 - Baja o borrado de datos. Para borrar uno o ms registros la clase SQLiteDatabase tiene un mtodo que le pasamos en el primer parmetro el nombre de la tabla y en el segundo la condicin que debe cumplirse para que se borre la fila de la tabla. El mtodo delete retorna un entero que indica la cantidad de registros borrados:
publ i c voi d baj a( Vi ew v) { Admi nSQLi t eOpenHel per admi n=new Admi nSQLi t eOpenHel per ( t hi s, " admi ni st r aci on" , nul l , 1) ; SQLi t eDat abase bd=admi n. get Wr i t abl eDat abase( ) ; St r i ng dni =et 1. get Text ( ) . t oSt r i ng( ) ; i nt cant =bd. del et e( " vot ant es" , " dni =" +dni +" " , nul l ) ; bd. cl ose( ) ; et 1. set Text ( " " ) ; et 2. set Text ( " " ) ; et 3. set Text ( " " ) ; et 4. set Text ( " " ) ; i f ( cant ==1) Toast . makeText ( t hi s, " Se bor r l a per sona con di cho document o" , Toast . LENGTH_SHORT) . show( ) ; el se Toast . makeText ( t hi s, " No exi st e una per sona con di cho document o" , Toast . LENGTH_SHORT) . show( ) ; }
4 - Modificacin de datos. En la modificacin de datos debemos crear un objeto de la clase ContentValues y mediante el mtodo put almacenar los valores para cada campo que ser modificado. Luego se llama al mtodo update de la clase SQLiteDatabase pasando el nombre de la tabla, el objeto de la clase ContentValues y la condicin del where (el cuanto parmetro en este ejemplo no se lo emplea)
publ i c voi d modi f i caci on( Vi ew v) { Admi nSQLi t eOpenHel per admi n=new Admi nSQLi t eOpenHel per ( t hi s, " admi ni st r aci on" , nul l , 1) ; SQLi t eDat abase bd=admi n. get Wr i t abl eDat abase( ) ; St r i ng dni =et 1. get Text ( ) . t oSt r i ng( ) ; St r i ng nombr e=et 2. get Text ( ) . t oSt r i ng( ) ; St r i ng col egi o=et 3. get Text ( ) . t oSt r i ng( ) ; St r i ng nr omesa=et 4. get Text ( ) . t oSt r i ng( ) ; Cont ent Val ues r egi st r o=new Cont ent Val ues( ) ; r egi st r o. put ( " nombr e" , nombr e) ; r egi st r o. put ( " col egi o" , col egi o) ; r egi st r o. put ( " nr omesa" , nr omesa) ; i nt cant = bd. updat e( " vot ant es" , r egi st r o, " dni =" +dni , nul l ) ; bd. cl ose( ) ; i f ( cant ==1) Toast . makeText ( t hi s, " se modi f i car on l os dat os" , Toast . LENGTH_SHORT) . show( ) ; el se Toast . makeText ( t hi s, " no exi st e una per sona con di cho document o" , Toast . LENGTH_SHORT) . show( ) ; }
Final del proyecto015.
15 - Ventana de propiedades (Properties)
Hasta ahora siempre que queremos modificar propiedades de un objeto debemos presionar el botn derecho del mouse y mediante el men contextual proceder a accederla y modificarla:
Otra forma de acceder a estas propiedades es la apertura de la ventana de properties, para esto desde el men de Eclipse procedemos a seleccionar la opcin: Window ->Show View ->Other...:
Ahora seleccionamos en el dilogo siguiente en el cuadro General el cono de Properties:
Ahora cuando disponemos objetos sobre el formulario o lienzo de nuestra aplicacin podemos ver todas las propiedades del objetos seleccionado y modificarlas desde esta ventana:
Por ejemplo si queremos definir la propiedad On Click de un objeto Button debemos seleccionarlo y en la ventana de propiedades cargamos el valor para dicha propiedad:
16 - Layout (LinearLayout)
Android organiza las componentes visuales (Button, EditText, TextView etc.) en pantalla mediante contenedores llamados Layout.
Hasta ahora no nos a preocupado como organizar una pantalla, sino nos hemos centrado en la funcionalidad de cada programa que implementamos.
Ahora comenzaremos a preocuparnos como organizar y disponer las componentes dentro de la pantalla.
- LinearLayout.
LinearLayout es uno de los diseos ms simples y ms empleado. Simplemente establece los componentes visuales uno junto al otro, ya sea horizontal o verticalmente (nosotros hemos empleado hasta ahora el LinearLayout disponiendo los componentes verticalmente)
Una de las propiedades ms importantes del contenedor LinearLayout es Orientation.
Si fijamos la propiedad Orientation con el valor Vertical luego las componentes contenidas en el Layout se disponen una debajo de otra (Cuando disponemos un contenedor LinearLayout por defecto se inicializa la propiedad Orientation en Vertical):
En cambio si fijamos la propiedad Orientation con el valor Horizontal el resultado es la disposicin de las componentes en forma horizontal:
Otra propiedad pero en este caso perteneciente a los controles visuales (Button, EditText, TextView etc.) y que tiene sentido emplearla cuando utilizamos un LinearLayout es la propiedad Layout_weight (Define la cantidad de espacio extra en el diseo que debe ser asignado al control) Por ejemplo si queremos disponer un control de tipo EditText y un Button en un LinearLayout y que el EditText se apropie el 70% del espacio restante y el botn el 30% restante debemos fijar los valores de las propiedades Layout_weight con los nmeros 0.7 y 0.3 respectivamente:
Podemos disponer ms de una componente de tipo LinearLayout para implementar nuestra interfaz visual. Veamos los objetos y propiedades a configurar si queremos la siguiente interfaz:
Para implementar este interfaz hemos agregado de la pestaa "Layouts" dos controles de tipo uno de tipo "LinearLayout (Vertical)" en la parte superior y uno de tipo "LinearLayout (Horizontal)" en la parte inferior:
Disponemos un TextView y un EditText en el LinearLayout superior:
Ahora en el otro LinearLayout agregamos un Button y un TextView:
Para que el segundo LinearLayout quede en la parte inferior de la pantalla inicializamos las propiedades "Layout_weight" con 1 para el superior y con 0 para el inferior:
Seleccionamos el EditText del primer LinearLayout y actualizamos las propiedades "Background" (con el color blanco #ffffff) y Layout Width con el valor Match Parent (para que ocupe todo el espacio del contenedor), tambin actualizamos el valor de la propiedad Text color con el valor #000000:
Finalmente actualizamos el segundo EditText con lo que tenemos como resultado la interfaz:
Propiedad Gravity.
Otra propiedad muy utilizada es Gravity. Esta propiedad nos permite alinear a la izquierda, a la derecha, a la parte superior, a la parte superior derecha etc.
Para implementar la siguiente interfaz:
Para el LinearLayout superior definimos la propiedad Layout_weight con valor 0 y el segundo LinearLayout la misma propiedad Layout_weight con valor 1. Los dos botones que ubicamos en el segundo LinearLayout aparecen en la parte inferior derecha ya que inicializamos la propiedad Gravity del segundo LinearLayout con los valores:
17 - Layout (TableLayout)
El Layout de tipo TableLayout agrupa componentes en filas y columnas. Un TableLayout contiene un conjunto de componentes de tipo TableRow que es el que agrupa componentes visuales por cada fila (cada fila puede tener distinta cantidad de componentes visuales)
Cuando disponemos un control de Layouts de tipo TableLayout automticamente crea cuatro componentes de tipo TableRow que los podemos ver en la ventana "Outline". Podemos borrar o agregar componentes de tipo TableRow segn las necesidades de nuestro TableLayout:
Luego de borrar un control de tipo TableRow y agregar componentes de tipo Button la interfaz visual queda como sigue:
Otra propiedad que nos puede ser til inicializar en los controles que se disponen dentro de un TableLayout es layout_span. Esta propiedad permite que un control se expanda ms de una celda.
En el siguiente ejemplo el objeto de la clase Button de la segunda fila hemos dispuesto la propiedad layout_span con el valor 2:
Si la propiedad no aparece en la ventana "Properties" cuando seleccionamos el objeto debemos entrar al archivo XML y agregar manualmente dicha propiedad:
18 - Layout (RelativeLayout)
Hay varias posibilidades cuando empleamos el RelativeLayout. Primero podemos alinear un control con respecto al Layout que lo contiene. Para probar esto dispondremos un control de tipo RelativeLayout y fijaremos la propiedad Layout_weight con el valor 1 (esto hace que el RelativeLayout ocupe completamente la pantalla) Luego dispondremos un botn en cada vrtice y veremos que propiedades son afectadas e inicializadas:
Como podemos ver cada control que agregamos se inicializan alguna de las propiedades:
al i gnPar ent Lef t al i gnPar ent Ri ght al i gnPar ent Top al i gnPar ent Bot t om cent er Hor i zont al cent er Ver t i cal cent er I nPar ent
Con este tipo de layout podemos disponer un control en forma relativa a otro control que haya dentro del RelativeLayout. Veamos un ejemplo:
En este ejemplo hemos dispuesto el segundo botn debajo (below) del botn 1 y alineado a la izquierda (luego si desplazamos el botn 1 se desplazar el botn 2)
La posicin relativa con respecto a otro control puede ser:
above ( por enci ma) bel ow ( debaj o) t oLef t Of ( a l a i zqui er da de) t oRi ght Of ( a l a der echa)
19 - Layout (FrameLayout)
El control de tipo FrameLayout dispone dentro del contenedor todos los controles visuales alineados al vrtice superior izquierdo. Es decir si disponemos dos o ms controles los mismos se apilan.
Por ejemplo si disponemos dentro de un FrameLayout un ImageView y un Button luego el botn se superpone a la imagen:
Otra aplicacin del control FrameLayout es disponer una serie de controles visuales no visibles e ir alternando cual se hace visible.
Problema: Disponer un ImageView y un Button dentro de un layout FrameLayout. Cuando se inicia la aplicacin mostrar solo el botn y al ser presionado ocultar el botn y hacer visible la imagen que muestra el ImageView.
Creamos una interfaz visual similar a la siguiente:
Seleccionamos el control ImageView y fijarmos la propiedad Visibility con el valor invisible (esto hace que la imagen no se muestre en pantalla)
Luego inicializamos la propiedad On click del control Button indicando el nombre del mtodo que se ejecutar al ser presionado:
El cdigo fuente de la clase es:
package andr oi d. pr oyect o016;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . But t on; i mpor t andr oi d. wi dget . I mageVi ew;
publ i c cl ass Pr oyect o016Act i vi t y ext ends Act i vi t y { But t on b1; I mageVi ew i v1; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
b1=( But t on) f i ndVi ewByI d( R. i d. but t on1) ; i v1=( I mageVi ew) f i ndVi ewByI d( R. i d. i mageVi ew1) ; }
publ i c voi d ocul t ar Bot on( Vi ew v) { b1. set Vi si bi l i t y( Vi ew. I NVI SI BLE) ; i v1. set Vi si bi l i t y( Vi ew. VI SI BLE) ; } } Cuando se presiona el botn procedemos a ocultar el botn y hacer visible la imagen: publ i c voi d ocul t ar Bot on( Vi ew v) { b1. set Vi si bi l i t y( Vi ew. I NVI SI BLE) ; i v1. set Vi si bi l i t y( Vi ew. VI SI BLE) ; }
Final del proyecto016.
20 - Layout (ScrollView y LinearLayout)
El ScrollView junto con un LinearLayout nos permite disponer una cantidad de componentes visuales que superan la cantidad de espacio del visor del celular o tablet. Luego el usuario puede desplazar con el dedo la interfaz creada.
Problema: Disponer un control de tipo ScrollView (que se encuentra en la pestaa Composite). Como veremos automticamente se crea una componente de tipo LinearLayout e fijemos la propiedad Orientation del LinearLayout con el valor vertical:
Luego dispongamos numerosos botones que superen la cantidad de espacio del dispositivo. Numerar los botones con los nmeros del 1 en adelante:
Luego si ejecutamos el programa veremos que podemos desplazar (scroll) todo el contenido del visor con el dedo:
Final del proyecto017.
Otra posibilidad para la implementacin de una interfaz en Android es disponer un LinearLayout en la parte superior y un ScrollView en la parte inferior:
Esto hace que en tiempo de ejecucin quede fijo el LinearLayout y podamos desplazar con el dedo el ScrollView que aparece en la parte inferior:
21 - Icono de la aplicacin
Cuando creamos un proyecto para implementar una aplicacin con el plugin de Android nos crea un cono por defecto:
Los conos e imgenes se almacenan en la carpeta res (resources) y en esta hay tres carpetas llamadas:
dr awabl e- mdpi dr awabl e- l dpi dr awabl e- hdpi
Y en cada una de estas hay un archivo llamado icon.png:
Como las resoluciones de los dispositivos Android pueden ser muy distintos (un celular, una tablet, un televisor etc.) se recomienda proporcionar mltiples copias de cada imagen de recursos a diferentes resoluciones y almacenarlos en las carpetas nombradas respetando las siguientes reglas:
r es/ dr awabl e- mdpi / El cono debe ser de 48*48 p xel es. r es/ dr awabl e- l dpi / 75%del t amao de l as i mgenes al macenadas en l a car pet a dr awabl e- mdpi El cono debe ser de 36*36 p xel es. r es/ dr awabl e- hdpi / 150%del t amao de l as i mgenes al macenadas en l a car pet a dr awabl e- mdpi El cono debe ser de 72*72 p xel es.
En las versiones ms actuales de Android se propone crear una cuarta carpeta llamada:
r es/ dr awabl e- xhdpi / 200%del t amao de l as i mgenes al macenadas en l a car pet a dr awabl e- mdpi
Problema: Crear una aplicacin, dibujar y almacenar tres archivos llamados icon.png. Tener en cuenta que el archivo que se almacena en la carpeta drawable-mdpi debe ser de 48 pxeles, el de la carpeta drawable-mdpi de 36 pxeles y el de la carpeta drawable-hdpi debe ser de 72 pxeles de ancho y alto. Ejecutar la aplicacin y ver el cono nuevo.
Final del proyecto018.
22 - Reproduccin de audio (archivo contenido en la aplicacin)
Veremos los pasos para reproducir un archivo mp3 (otros formatos soportados por Android son: Ogg, Wav)
Problema: Disponer dos botones con las etiquetas: Gato y Len, luego cuando se presione reproducir el archivo de audio respectivo. Los archivos de sonidos almacenarlos en la misma aplicacin.
Luego de crear el proyecto procedemos a crear una carpeta llamada raw que dependa de la carpeta res, almacenamos los dos archivos mp3 en dicha carpeta:
Luego de copiar los archivos a la carpeta debemos refrescar los archivos contenidos en el proyecto presionando el botn derecho del mouse y seleccionando la opcin "Refresh":
Podemos comprobar que los dos archivos estn referenciados en el proyecto.
Creamos una interfaz con dos botones e inicializamos las propiedades Text y On Click de cada botn:
El cdigo fuente de la clase Proyecto019Activity.java es: package andr oi d. pr oyect o019;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. medi a. Medi aPl ayer ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew;
publ i c cl ass Pr oyect o019Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
publ i c voi d pr esi onGat o( Vi ew v) { Medi aPl ayer mp=Medi aPl ayer . cr eat e( t hi s, R. r aw. gat o) ; mp. st ar t ( ) ; }
publ i c voi d pr esi onLeon( Vi ew v) { Medi aPl ayer mp=Medi aPl ayer . cr eat e( t hi s, R. r aw. l eon) ; mp. st ar t ( ) ; } }
Cuando copiamos los archivos mp3 se genera luego en la clase R la referencia a los dos archivos y posteriormente los podemos rescatar cuando creamos un objeto de la clase MediaPlayer:
Medi aPl ayer mp=Medi aPl ayer . cr eat e( t hi s, R. r aw. gat o) ;
Seguidamente llamamos al mtodo start:
mp. st ar t ( ) ;
Final del proyecto019.
23 - Reproduccin, pausa, continuacin y detencin de un archivo de audio.
Problema: Confeccionar una aplicacin que permita Iniciar un archivo mp3, detener, continuar, detener en forma definitiva y activacin o no de la reproduccin en forma circular.
Crear un archivo mp3 con el programa Audacity contando del 1 al 30.
Primero creamos un proyecto y definimos los 5 botones y mtodos a ejecutar cuando se presionen los botones respectivos:
Creamos la carpeta raw y almacenamos en la misma el archivo mp3 creado previamente. Refrescamos la carpeta raw para actualizar el archivo mp3:
El cdigo fuente es: package andr oi d. pr oyect o020;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. medi a. Medi aPl ayer ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . But t on;
publ i c cl ass Pr oyect o020Act i vi t y ext ends Act i vi t y { Medi aPl ayer mp; But t on b1; i nt posi ci on=0;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; b1=( But t on) f i ndVi ewByI d( R. i d. but t on5) ; }
publ i c voi d dest r ui r ( ) { i f ( mp! =nul l ) mp. r el ease( ) ; }
publ i c voi d i ni ci ar ( Vi ew v) { dest r ui r ( ) ; mp = Medi aPl ayer . cr eat e( t hi s, R. r aw. numer os) ; mp. st ar t ( ) ; St r i ng op=b1. get Text ( ) . t oSt r i ng( ) ; i f ( op. equal s( " No r epr oduci r en f or ma ci r cul ar " ) ) mp. set Loopi ng( f al se) ; el se mp. set Loopi ng( t r ue) ; }
publ i c voi d pausar ( Vi ew v) { i f ( mp ! = nul l && mp. i sPl ayi ng( ) ) { posi ci on = mp. get Cur r ent Posi t i on( ) ; mp. pause( ) ; } }
publ i c voi d cont i nuar ( Vi ew v) { i f ( mp ! = nul l && mp. i sPl ayi ng( ) ==f al se) { mp. seekTo( posi ci on) ; mp. st ar t ( ) ; } }
publ i c voi d det ener ( Vi ew v) { i f ( mp ! = nul l ) { mp. st op( ) ; posi ci on = 0; } }
publ i c voi d ci r cul ar ( Vi ew v) { det ener ( nul l ) ; St r i ng op=b1. get Text ( ) . t oSt r i ng( ) ; i f ( op. equal s( " No r epr oduci r en f or ma ci r cul ar " ) ) b1. set Text ( " r epr oduci r en f or ma ci r cul ar " ) ; el se b1. set Text ( " No r epr oduci r en f or ma ci r cul ar " ) ; } }
Primero definimos tres atributos uno de la clase MediaPlayer para administrar el archivo mp3, un entero donde se almacena la posicin actual de reproduccin en milisegundos (para poder continuarla en el futuro) y la referencia de un objeto de la clase Button:
Medi aPl ayer mp; But t on b1; i nt posi ci on=0;
El mtodo destruir verifica con un if si el objeto de la clase MediaPlayer est creado procede a liberar recursos del mismo llamando al mtodo release:
publ i c voi d dest r ui r ( ) { i f ( mp! =nul l ) mp. r el ease( ) ; }
El mtodo iniciar que se ejecuta al presionar el botn "Iniciar" primero llama al mtodo destruir (para el caso que el mp3 este en ejecucin actualmente) seguidamente creamos un objeto de la clase MediaPlayer llamando al mtodo create (en este hacemos referencia al archivo que copiamos a la carpeta raw) Llamamos al mtodo start. Por ltimo extraemos el texto del quinto botn y verificamos si la reproduccin debe ejecutarse en forma circular (en forma indefinida una y otra vez):
publ i c voi d i ni ci ar ( Vi ew v) { dest r ui r ( ) ; mp = Medi aPl ayer . cr eat e( t hi s, R. r aw. numer os) ; mp. st ar t ( ) ; St r i ng op=b1. get Text ( ) . t oSt r i ng( ) ; i f ( op. equal s( " No r epr oduci r en f or ma ci r cul ar " ) ) mp. set Loopi ng( f al se) ; el se mp. set Loopi ng( t r ue) ; }
El mtodo pausar verifica que el objeto de la clase MediaPlayer este creado y en ejecucin, en caso afirmativo recuperamos la posicin actual de reproduccin y llamamos seguidamente al mtodo pause:
publ i c voi d pausar ( Vi ew v) { i f ( mp ! = nul l && mp. i sPl ayi ng( ) ) { posi ci on = mp. get Cur r ent Posi t i on( ) ; mp. pause( ) ; } }
El mtodo continuar verifica que el objeto de la clase MediaPlayer este creado y la propiedad isPlaying retorne false para proceder a posicionar en que milisegundo continuar la reproduccin:
publ i c voi d cont i nuar ( Vi ew v) { i f ( mp ! = nul l && mp. i sPl ayi ng( ) ==f al se) { mp. seekTo( posi ci on) ; mp. st ar t ( ) ; } }
El mtodo detener interrumpe la ejecucin del mp3 e inicializa el atributo posicion con cero:
publ i c voi d det ener ( Vi ew v) { i f ( mp ! = nul l ) { mp. st op( ) ; posi ci on = 0; } }
Cuando se presiona el botn que cambia si la reproduccin se efecta en forma circular o no procedemos a extraer su texto y segn dicho valor almacenamos el valor opuesto:
publ i c voi d ci r cul ar ( Vi ew v) { det ener ( nul l ) ; St r i ng op=b1. get Text ( ) . t oSt r i ng( ) ; i f ( op. equal s( " No r epr oduci r en f or ma ci r cul ar " ) ) b1. set Text ( " r epr oduci r en f or ma ci r cul ar " ) ; el se b1. set Text ( " No r epr oduci r en f or ma ci r cul ar " ) ; }
Final del proyecto020.
24 - Reproduccin de audio (archivo contenido en una tarjeta SD) El objetivo de este concepto es acceder a un archivo mp3 almacenado en la tarjeta SD de nuestro equipo.
Problema: Disponer un botn con la etiqueta: "Gato", luego cuando se presione reproducir el archivo de audio respectivo. El archivo de sonido almacenarlo en la tarjeta SD.
Luego de crear el proyecto debemos ejecutar la aplicacin en modo depuracin para poder acceder a la tarjeta SD que crea el emulador Android. Para ejecutar la aplicacin en modo "Debug" presionamos el botn derecha del mouse sobre el proyecto y seleccionamos la opcin "Debug A" "Android Aplication":
Una vez que se este ejecutando la aplicacin (no importa que todava no hemos implementado su funcionalidad) procedemos a abrir la ventana "File Explorer" de Android. Seleccionamos del men de opciones de Eclipse: Window ->Show View ->Other :
Y en esta ventana seleccionamos Android ->FileExplorer:
Ahora podemos ver la ventana donde administramos los archivos contenidos en la tarjeta SD que emula el "Android Virtual Device":
En la carpeta sdcard debemos subir el archivo mp3 (debemos seleccionar esta carpeta con el mouse)
Esto lo hacemos mediante un botn que aparece en la parte derecha de esta ventana "Push a file onto device", luego de esto tenemos el archivo montado en la tarjeta SD:
Ahora implementemos la interfaz de nuestra aplicacin (un solo botn) que cuando se presione llame al mtodo ejecutar:
El cdigo fuente es: package andr oi d. pr oyect o021;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. medi a. Medi aPl ayer ; i mpor t andr oi d. net . Ur i ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. os. Envi r onment ; i mpor t andr oi d. vi ew. Vi ew;
publ i c cl ass Pr oyect o021Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
publ i c voi d ej ecut ar ( Vi ew v) { Ur i dat os = Ur i . par se( Envi r onment . get Ext er nal St or ageDi r ect or y( ) . get Pat h( ) +" / gat o. mp3" ) ; Medi aPl ayer mp=Medi aPl ayer . cr eat e( t hi s, dat os) ; mp. st ar t ( ) ; } }
Creamos un objeto de la clase Uri llamando al mtodo parse donde indicamos el path y nombre del archivo a recuperar:
Ur i dat os = Ur i . par se( Envi r onment . get Ext er nal St or ageDi r ect or y( ) . get Pat h( ) +" / gat o. mp3" ) ;
Creamos el objeto de la clase MediaPlayer pasando ahora la referencia del objeto de la clase Uri:
Medi aPl ayer mp=Medi aPl ayer . cr eat e( t hi s, dat os) ;
Iniciamos la reproduccin del mp3:
mp. st ar t ( ) ;
Final del proyecto021.
Recordar que para ejecutar este proyecto se debe subir un archivo mp3 llamado "gato.mp3" a la tarjeta SD.
25 - Reproduccin de audio (archivo localizado en internet)
Ahora vamos a ver los pasos para reproducir un archivo almacenado en un servidor de internet.
Problema: Disponer un botn con la etiqueta: "Gato", luego cuando se presione reproducir el archivo de audio respectivo. El archivo de sonido se encuentra almacenado en http://www.codigofuenteya.com.ar/recursos/gato.mp3
El primer paso es modificar el archivo AndroidManifest.xml donde autorizamos a la aplicacin a acceder a recursos localizados en internet:
Creamos la interfaz de la aplicacin e inicializamos el evento On click del Button con el mtodo que implementaremos:
El cdigo fuente es: package andr oi d. pr oyect o022;
i mpor t j ava. i o. I OExcept i on;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. medi a. Medi aPl ayer ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew;
publ i c cl ass Pr oyect o022Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
publ i c voi d ej ecut ar ( Vi ew v) { Medi aPl ayer mp=new Medi aPl ayer ( ) ; t r y {
mp. set Dat aSour ce( " ht t p: / / www. codi gof uent eya. com. ar / r ecur sos/ gat o. mp3" ) ; mp. pr epar e( ) ; mp. st ar t ( ) ; }cat ch( I OExcept i on e) { } } }
Para recuperar un archivo mp3 de internet procedemos de la siguiente manera, primero creamos un objeto de la clase MediaPlayer:
Medi aPl ayer mp=new Medi aPl ayer ( ) ;
Luego llamamos al mtodo setDataSource indicando la direccin de internet donde se almacena el archivo mp3:
mp. set Dat aSour ce( " ht t p: / / www. codi gof uent eya. com. ar / r ecur sos/ gat o. mp3" ) ;
Llamamos al mtodo prepare y seguidamente llamamos a start:
mp. pr epar e( ) ; mp. st ar t ( ) ;
Todo esto lo hacemos en un bloque try/catch para capturar excepciones de tipo IOException. Esta primera aproximacin para ejecutar un mp3 localizado en internet bloquea la aplicacin hasta que se carga por completo el archivo, es decir queda ejecutndose el mtodo mp.prepare() hasta que finaliza la recuperacin en forma completa.
Final del proyecto022.
Problema: Confeccionar otra aplicacin similar a la anterior pero que no se congele la interfaz de la aplicacin mientras se carga el mp3. Mostrar un mensaje que el archivo se est cargando.
Desarrollamos un nuevo proyecto, asignamos el permiso de acceder a internet en el archivo AndroidManifest.xmp y creamos una interfaz similar al problema anterior.
El cdigo fuente es: package andr oi d. pr oyect o023;
i mpor t j ava. i o. I OExcept i on;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. medi a. Medi aPl ayer ; i mpor t andr oi d. medi a. Medi aPl ayer . OnPr epar edLi st ener ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass Pr oyect o023Act i vi t y ext ends Act i vi t y i mpl ement s OnPr epar edLi st ener { Medi aPl ayer mp; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
publ i c voi d ej ecut ar ( Vi ew v) { mp=new Medi aPl ayer ( ) ; mp. set OnPr epar edLi st ener ( t hi s) ; t r y {
mp. set Dat aSour ce( " ht t p: / / www. codi gof uent eya. com. ar / r ecur sos/ gat o. mp3" ) ; mp. pr epar eAsync( ) ; }cat ch( I OExcept i on e) { } Toast t =Toast . makeText ( t hi s, " Esper e un moment o mi ent r as se car ga el mp3" , Toast . LENGTH_SHORT) ; t . show( ) ; }
publ i c voi d onPr epar ed( Medi aPl ayer mp) { mp. st ar t ( ) ; } } Para poder capturar el evento que el archivo se termin de recuperar debemos implementar la interface OnPreparedListener:
publ i c cl ass Pr oyect o023Act i vi t y ext ends Act i vi t y i mpl ement s OnPr epar edLi st ener {
Con esto decimos que nuestra clase implementar el mtodo onPrepared donde iniciamos la ejecucin del mp3:
publ i c voi d onPr epar ed( Medi aPl ayer mp) { mp. st ar t ( ) ; }
En el evento click del botn creamos el objeto de la clase MediaPlayer, le pasamos al mtodo setOnPreparedListener la direccin del objeto que capturar el evento de que el recurso est completo. Luego llamamos a los mtodos setDataSource y prepareAsync para inicializar la carga del mp3. Finalmente mostramos un mensaje para informar al usuario que el archivo se est descargando:
publ i c voi d ej ecut ar ( Vi ew v) { mp=new Medi aPl ayer ( ) ; mp. set OnPr epar edLi st ener ( t hi s) ; t r y {
mp. set Dat aSour ce( " ht t p: / / www. codi gof uent eya. com. ar / r ecur sos/ gat o. mp3" ) ; mp. pr epar eAsync( ) ; }cat ch( I OExcept i on e) { } Toast t =Toast . makeText ( t hi s, " Esper e un moment o mi ent r as se car ga el mp3" , Toast . LENGTH_SHORT) ; t . show( ) ; }
Final del proyecto023.
26 - Reproduccin de audio utilizando el reproductor propio de Android (va Intent)
Otra forma de ejecutar un archivo mp3 es mediante el reproductor interno de Android. Esta aplicacin reproduce todos los formatos soportados por Android y tiene una interfaz que le ser familiar al usuario de nuestra aplicacin.
Problema: Disponer un botn con la etiqueta: "Ejecutar mp3 con el reproductor propio de Android", luego cuando se presione reproducir el archivo de audio respectivo con el reproductor de Android via Intent. El archivo de sonido almacenarlo en la tarjeta SD.
Luego de crear el proyecto debemos ejecutar la aplicacin en modo depuracin para poder acceder a la tarjeta SD que crea el emulador Android. Para ejecutar la aplicacin en modo "Debug" presionamos el botn derecha del mouse sobre el proyecto y seleccionamos la opcin "Debug A" "Android Aplication":
Una vez que se este ejecutando la aplicacin (no importa que todava no hemos implementado su funcionalidad) procedemos a abrir la ventana "File Explorer" de Android. Seleccionamos del men de opciones de Eclipse: Window ->Show View ->Other :
Y en esta ventana seleccionamos Android ->FileExplorer:
Ahora podemos ver la ventana donde administramos los archivos contenidos en la tarjeta SD que emula el "Android Virtual Device":
En la carpeta sdcard debemos subir el archivo mp3 (debemos seleccionar esta carpeta con el mouse)
Esto lo hacemos mediante un botn que aparece en la parte derecha de esta ventana "Push a file onto device", luego de esto tenemos el archivo montado en la tarjeta SD:
Creamos la interfaz con el Button y especificamos el evento On click:
El cdigo fuente es: package andr oi d. pr oyect o024;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . I nt ent ; i mpor t andr oi d. net . Ur i ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew;
publ i c cl ass Pr oyect o024Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
publ i c voi d ej ecut ar ( Vi ew v) { I nt ent i nt ent = new I nt ent ( andr oi d. cont ent . I nt ent . ACTI ON_VI EW) ; Ur i dat a = Ur i . par se( " f i l e: / / / sdcar d" +" / gat o. mp3" ) ; i nt ent . set Dat aAndType( dat a, " audi o/ mp3" ) ; st ar t Act i vi t y( i nt ent ) ; } }
Creamos un objeto de la clase Intent y un objeto de la clase Uri referenciando al archivo mp3 almacenado en la tarjeta SD. Indicamos mediante el mtodo setDataAndType el Uri y el tipo de archivo a reproducir. Activamos la aplicacin mediante startActivity.
Final del proyecto024.
27 - Grabacin de audio mediante el grabador provisto por Android (via Intent)
La forma ms sencilla de capturar audio en Android es mediante el grabador que provee el sistema operativo Android. Invocamos la aplicacin de grabacin (tiene como ventana que la interfaz le es familiar al usuario, ya que muchas aplicaciones utilizan esta caracterstica) y luego recuperamos el audio grabado.
Problema: Disponer dos objetos de la clase Button con las etiquetas "Grabar" y "Reproducir". Cuando se presione el primer botn proceder a activar la grabadora provista por Android. Cuando se presione el segundo botn reproducir el audio grabado.
Crear la interfaz e inicializar los eventos On click de cada botn:
El cdigo fuente es: package andr oi d. pr oyect o25;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . I nt ent ; i mpor t andr oi d. medi a. Medi aPl ayer ; i mpor t andr oi d. medi a. Medi aPl ayer . OnCompl et i onLi st ener ; i mpor t andr oi d. net . Ur i ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. pr ovi der . Medi aSt or e; i mpor t andr oi d. vi ew. Vi ew;
publ i c cl ass Pr oyect o025Act i vi t y ext ends Act i vi t y { i nt pet i ci on=1; Ur i ur l 1;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
publ i c voi d gr abar ( Vi ew v) { I nt ent i nt ent = new I nt ent ( Medi aSt or e. Audi o. Medi a. RECORD_SOUND_ACTI ON) ; st ar t Act i vi t yFor Resul t ( i nt ent , pet i ci on) ; }
publ i c voi d r epr oduci r ( Vi ew v) { Medi aPl ayer medi aPl ayer = Medi aPl ayer . cr eat e( t hi s, ur l 1) ; medi aPl ayer . st ar t ( ) ; }
pr ot ect ed voi d onAct i vi t yResul t ( i nt r equest Code, i nt r esul t Code, I nt ent dat a) { i f ( r esul t Code == RESULT_OK && r equest Code == pet i ci on) { ur l 1 = dat a. get Dat a( ) ; } }
}
Cuando se presiona el botn de grabar el audio mediante un Intent activamos la aplicacin de grabacin propia de Android.
Seguidamente llamamos al mtodo startActivityForResult para poder recuperar la grabacin luego de finalizada a travs del mtodo onActivityResult:
publ i c voi d gr abar ( Vi ew v) { I nt ent i nt ent = new I nt ent ( Medi aSt or e. Audi o. Medi a. RECORD_SOUND_ACTI ON) ; st ar t Act i vi t yFor Resul t ( i nt ent , pet i ci on) ; }
Debemos pasar al mtodo startActivityForResult adems de la referencia del Intent una variable con un valor 0 o positivo (luego este valor retornar al mtodo onActivityResult)
Cuando finalizamos la grabacin se ejecuta el mtodo onActivityResult, donde almacenamos en la variable url1 la referencia al archivo de audio creado:
pr ot ect ed voi d onAct i vi t yResul t ( i nt r equest Code, i nt r esul t Code, I nt ent dat a) { i f ( r esul t Code == RESULT_OK && r equest Code == pet i ci on) { ur l 1 = dat a. get Dat a( ) ; } }
Por ltimo para ejecutar el contenido de la grabacin utilizamos la clase ya vista MediaPlayer:
publ i c voi d r epr oduci r ( Vi ew v) { Medi aPl ayer medi aPl ayer = Medi aPl ayer . cr eat e( t hi s, ur l 1) ; medi aPl ayer . st ar t ( ) ; }
Final del proyecto025.
28 - Captura de audio mediante la clase MediaRecorder
Otra forma de grabar audio en Android es el empleo de la clase MediaRecorder. Esta clase nos da ms libertades a la hora de construir una aplicacin que requiere grabar audio.
Problema: Disponer tres objetos de la clase Button con las etiquetas "Grabar", "Detener Grabacin" y "Reproducir Grabacin". Disponer adems un TextView para informar del estado actual.
Cuando se presione el botn "Grabar" permitir registrar todos los sonidos hasta que se presione el botn "Detener Grabacin". Cuando se presione el botn "Reproducir Grabacin" emitir el archivo de audio previamente generado.
La interfaz visual a implementar es la siguiente:
Tener en cuenta de no olvidar definir los tres mtodos para los tres botones: grabar, detener y reproducir.
Tambin debemos modificar el archivo AndroidManifest.xml donde debemos indicar que nuestra aplicacin acceder a la grabadora de sonido y a la tarjeta SD donde se almacenar el archivo de sonido.
Esto lo hacemos seleccionando el archivo AndroidManifest.xml y en la pestaa Permissions registramos los dos permisos:
El cdigo fuente es: package andr oi d. pr oyect o026;
i mpor t j ava. i o. Fi l e; i mpor t j ava. i o. I OExcept i on; i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. medi a. Medi aPl ayer ; i mpor t andr oi d. medi a. Medi aRecor der ; i mpor t andr oi d. medi a. Medi aPl ayer . OnCompl et i onLi st ener ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. os. Envi r onment ; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . But t on; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o026Act i vi t y ext ends Act i vi t y i mpl ement s OnCompl et i onLi st ener { Text Vi ew t v1; Medi aRecor der r ecor der ; Medi aPl ayer pl ayer ; Fi l e ar chi vo; But t on b1, b2, b3;
/ ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
t v1 = ( Text Vi ew) t hi s. f i ndVi ewByI d( R. i d. t v1) ; b1=( But t on) f i ndVi ewByI d( R. i d. but t on1) ; b2=( But t on) f i ndVi ewByI d( R. i d. but t on2) ; b3=( But t on) f i ndVi ewByI d( R. i d. but t on3) ; }
publ i c voi d gr abar ( Vi ew v) { r ecor der = new Medi aRecor der ( ) ; r ecor der . set Audi oSour ce( Medi aRecor der . Audi oSour ce. MI C) ; r ecor der . set Out put For mat ( Medi aRecor der . Out put For mat . THREE_GPP) ; r ecor der . set Audi oEncoder ( Medi aRecor der . Audi oEncoder . AMR_NB) ; Fi l e pat h = new Fi l e( Envi r onment . get Ext er nal St or ageDi r ect or y( ) . get Pat h( ) ) ; t r y { ar chi vo = Fi l e. cr eat eTempFi l e( " t empor al " , " . 3gp" , pat h) ; } cat ch ( I OExcept i on e) { } r ecor der . set Out put Fi l e( ar chi vo. get Absol ut ePat h( ) ) ; t r y { r ecor der . pr epar e( ) ; } cat ch ( I OExcept i on e) { } r ecor der . st ar t ( ) ; t v1. set Text ( " Gr abando" ) ; b1. set Enabl ed( f al se) ; b2. set Enabl ed( t r ue) ; }
publ i c voi d det ener ( Vi ew v) { r ecor der . st op( ) ; r ecor der . r el ease( ) ; pl ayer = new Medi aPl ayer ( ) ; pl ayer . set OnCompl et i onLi st ener ( t hi s) ; t r y { pl ayer . set Dat aSour ce( ar chi vo. get Absol ut ePat h( ) ) ; } cat ch ( I OExcept i on e) { } t r y { pl ayer . pr epar e( ) ; } cat ch ( I OExcept i on e) { } b1. set Enabl ed( t r ue) ; b2. set Enabl ed( f al se) ; b3. set Enabl ed( t r ue) ; t v1. set Text ( " Li st o par a r epr oduci r " ) ; }
publ i c voi d r epr oduci r ( Vi ew v) { pl ayer . st ar t ( ) ; b1. set Enabl ed( f al se) ; b2. set Enabl ed( f al se) ; b3. set Enabl ed( f al se) ; t v1. set Text ( " Repr oduci endo" ) ; }
publ i c voi d onCompl et i on( Medi aPl ayer mp) { b1. set Enabl ed( t r ue) ; b2. set Enabl ed( t r ue) ; b3. set Enabl ed( t r ue) ; t v1. set Text ( " Li st o" ) ; } }
Declaramos un objeto de la clase MediaRecorder para grabar audio:
Medi aRecor der r ecor der ;
Declaramos un objeto de la clase MediaPlayer para reproducir el archivo de sonido generado:
Medi aPl ayer pl ayer ;
Declaramos un objeto de la clase File que hace referencia al archivo que se crear:
Fi l e ar chi vo;
Declaramos las variables que harn referencia a los tres botones y al TextView:
Text Vi ew t v1; But t on b1, b2, b3;
En el mtodo onCreate obtenemos la referencia de los cuatro objetos creados en el archivo XML:
t v1 = ( Text Vi ew) t hi s. f i ndVi ewByI d( R. i d. t v1) ; b1=( But t on) f i ndVi ewByI d( R. i d. but t on1) ; b2=( But t on) f i ndVi ewByI d( R. i d. but t on2) ; b3=( But t on) f i ndVi ewByI d( R. i d. but t on3) ;
El mtodo ms importante de este concepto es el grabar:
publ i c voi d gr abar ( Vi ew v) { r ecor der = new Medi aRecor der ( ) ; r ecor der . set Audi oSour ce( Medi aRecor der . Audi oSour ce. MI C) ; r ecor der . set Out put For mat ( Medi aRecor der . Out put For mat . THREE_GPP) ; r ecor der . set Audi oEncoder ( Medi aRecor der . Audi oEncoder . AMR_NB) ; Fi l e pat h = new Fi l e( Envi r onment . get Ext er nal St or ageDi r ect or y( ) . get Pat h( ) ) ; t r y { ar chi vo = Fi l e. cr eat eTempFi l e( " t empor al " , " . 3gp" , pat h) ; } cat ch ( I OExcept i on e) { } r ecor der . set Out put Fi l e( ar chi vo. get Absol ut ePat h( ) ) ; t r y { r ecor der . pr epar e( ) ; } cat ch ( I OExcept i on e) { } r ecor der . st ar t ( ) ; t v1. set Text ( " Gr abando" ) ; b1. set Enabl ed( f al se) ; b2. set Enabl ed( t r ue) ; }
Creamos un objeto de la clase MediaRecorder:
r ecor der = new Medi aRecor der ( ) ;
Seguidamente definimos el micrfono como fuente de audio:
r ecor der . set Audi oSour ce( Medi aRecor der . Audi oSour ce. MI C) ;
Luego llamamos al mtodo setOutputFormat especificando que el archivo ser almacenado con la especificacin 3GPP y con extensin .3gp
r ecor der . set Out put For mat ( Medi aRecor der . Out put For mat . THREE_GPP) ;
Especificamos el codec a emplear llamando al mtodo setAudioEncoder:
r ecor der . set Audi oEncoder ( Medi aRecor der . Audi oEncoder . AMR_NB) ;
Obtenemos el path de la tarjeta SD y creamos un archivo temporal con extensin 3gp:
Fi l e pat h = new Fi l e( Envi r onment . get Ext er nal St or ageDi r ect or y( ) . get Pat h( ) ) ; t r y { ar chi vo = Fi l e. cr eat eTempFi l e( " t empor al " , " . 3gp" , pat h) ; } cat ch ( I OExcept i on e) { }
Con el mtodo setOutputFile de la clase MediaRecorder le indicamos el archivo donde debe almacenarse la grabacin:
r ecor der . set Out put Fi l e( ar chi vo. get Absol ut ePat h( ) ) ;
Llamamos al mtodo prepare y finalmente al mtodo start para comenzar la grabacin:
t r y { r ecor der . pr epar e( ) ; } cat ch ( I OExcept i on e) { } r ecor der . st ar t ( ) ;
El mtodo detener:
publ i c voi d det ener ( Vi ew v) { r ecor der . st op( ) ; r ecor der . r el ease( ) ; pl ayer = new Medi aPl ayer ( ) ; pl ayer . set OnCompl et i onLi st ener ( t hi s) ; t r y { pl ayer . set Dat aSour ce( ar chi vo. get Absol ut ePat h( ) ) ; } cat ch ( I OExcept i on e) { } t r y { pl ayer . pr epar e( ) ; } cat ch ( I OExcept i on e) { } b1. set Enabl ed( t r ue) ; b2. set Enabl ed( f al se) ; b3. set Enabl ed( t r ue) ; t v1. set Text ( " Li st o par a r epr oduci r " ) ; }
Llamamos primero al mtodo stop de la clase MediaRecorder y liberamos los recursos consumidos llamando a release:
r ecor der . st op( ) ; r ecor der . r el ease( ) ;
Creamos un objeto de la clase MediaPlayer para poder reproducir el archivo de audio que acabamos de grabar. Indicamos mediante el mtodo setOnCompletionListener la referencia de la clase que ser informada cuando el audio finalice:
pl ayer = new Medi aPl ayer ( ) ; pl ayer . set OnCompl et i onLi st ener ( t hi s) ;
Referenciamos el archivo a que debe reproducir:
t r y { pl ayer . set Dat aSour ce( ar chi vo. get Absol ut ePat h( ) ) ; } cat ch ( I OExcept i on e) { }
Finalmente llamamos al mtodo prepare de la clase MediaPlayer:
t r y { pl ayer . pr epar e( ) ; } cat ch ( I OExcept i on e) { }
El mtodo reproducir simplemente llama al mtodo start de la clase MediaPlayer para iniciar la reproduccin del archivo previamente grabado:
publ i c voi d r epr oduci r ( Vi ew v) { pl ayer . st ar t ( ) ; b1. set Enabl ed( f al se) ; b2. set Enabl ed( f al se) ; b3. set Enabl ed( f al se) ; t v1. set Text ( " Repr oduci endo" ) ; }
El mtodo onCompletion se ejecuta cuando termina de reproducirse el archivo de audio:
publ i c voi d onCompl et i on( Medi aPl ayer mp) { b1. set Enabl ed( t r ue) ; b2. set Enabl ed( t r ue) ; b3. set Enabl ed( t r ue) ; t v1. set Text ( " Li st o" ) ; }
Final del proyecto026.
29 - Men de opciones
En Android la implementacin de un men de opciones permite mostrar opciones de una forma estandarizada entre aplicaciones (esto hace que todos los programas tengan una vista de un men muy parecidos)
Los mens aparecen en la parte inferior de la pantalla cuando el usuario presiona el botn Men del celular.
La implementacin del men se puede hacer de forma similar a la interfaz visual de la aplicacin mediante la creacin de un archivo XML y la construccin del mismo empleando las herramientas que provee el plugin de Eclipse para Android.
Problema: Confeccionar una aplicacin que muestre un men con dos opciones: una que visualice el "Acerca de..." (nombre de la aplicacin, programador etc.) del programa y otra que finalice el programa.
Lo primero que hacemos es crear el archivo XML que contendr el men de opciones (presionamos el botn derecho del mouse sobre la carpeta res de nuestro proyecto y seleccionamos New ->Android XML File):
Aparece un dilogo donde debemos indicar el nombre del archivo de recursos a crear (lo llamamos menu1, este es el nombre del archivo XML que se crear en una carpeta llamada menu que depende de la carpeta res) y seleccionamos el RadioButton de menu:
Ya tenemos una nueva carpeta llamada menu y un archivo llamado menu1:
La intefaz del editor de menu que nos provee el plugin de Android para Eclipse es:
Procedemos a insertar la primera opcin presionando el botn "Add", seguidamente seleccionamos "Item":
Luego nos queda inicializar como mnimo el ttulo de que mostrar dicha opcin:
Ahora nuevamente presionamos el botn "Add" para aadir la segunda opcin. En el dilogo que aparece seleccionamos "Create a new element at the top level, in Menu", seguidamente seleccionamos "Item" y confirmamos:
Configuramos la propiedad Title de la segunda opcin:
Paso seguido debemos sobreescribir los mtodos onCreateOptionsMenu y onOptionsItemSelected heredados de la clase Activity.
El cdigo fuente de la clase Proyecto027Activity.java es: package andr oi d. pr oyect o027;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Menu; i mpor t andr oi d. vi ew. MenuI nf l at er ; i mpor t andr oi d. vi ew. MenuI t em; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass Pr oyect o027Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
@Over r i de publ i c bool ean onCr eat eOpt i onsMenu( Menu menu) { MenuI nf l at er i nf l at er =get MenuI nf l at er ( ) ; i nf l at er . i nf l at e( R. menu. menu1, menu) ; r et ur n t r ue; }
@Over r i de publ i c bool ean onOpt i onsI t emSel ect ed( MenuI t emi t em) { swi t ch ( i t em. get I t emI d( ) ) { case R. i d. i t em1: Toast . makeText ( t hi s, " Pr ogr amador : Di ego ( 23/ 08/ 2011) " , Toast . LENGTH_SHORT) . show( ) ; br eak; case R. i d. i t em2: f i ni sh( ) ; } r et ur n t r ue; } }
En el mtodo onCreateOptionsMenu creamos un objeto de la clase MenuInflater y mediante el mtodo inflate vinculamos el identificador del archivo de recursos: R.menu.menu1 y el objeto de la clase menu que llega como parmetro. Debemos retornar true:
@Over r i de publ i c bool ean onCr eat eOpt i onsMenu( Menu menu) { MenuI nf l at er i nf l at er =get MenuI nf l at er ( ) ; i nf l at er . i nf l at e( R. menu. menu1, menu) ; r et ur n t r ue; }
En el mtodo onOptionsItemSelected debemos disponer un switch para identificar cual de las opciones del men fue seleccionado. El parmetro item de la clase MenuItem tiene la referencia del objeto que fue pulsado. Luego obtenemos su Id llamando al mtodo getItemId y a travs del switch verificamos con el recurso que coincide y procedemos a efectuar la actividad respectiva (si se selecciona la primer opcin mostramos un mensaje mediante la clase Toast, si se seleccion la segunda opcin llamamos al mtodo finish para finalizar el programa:
@Over r i de publ i c bool ean onOpt i onsI t emSel ect ed( MenuI t emi t em) { swi t ch ( i t em. get I t emI d( ) ) { case R. i d. i t em1: Toast . makeText ( t hi s, " Pr ogr amador : Di ego ( 23/ 08/ 2011) " , Toast . LENGTH_SHORT) . show( ) ; br eak; case R. i d. i t em2: f i ni sh( ) ; } r et ur n t r ue; }
Desde el emulador para activar el men debemos presionar el siguiente botn:
Final del proyecto027.
30 - Men de opciones con submen
Ahora veremos que podemos desplegar un submen cuando se selecciona una opcin del men principal.
Problema: Confeccionar una aplicacin que muestre un men con dos opciones: una que visualice el texto "Sitios interesantes..." y al ser seleccionado muestre otro submen con una serie de buscadores. y otra opcin en el men principal para que finalice el programa.
Creamos el archivo "Android XML File" siguiendo los mismos pasos indicados en el concepto anterior, procedemos a crear el primer Item y luego creamos el submen para dicho menuitem como lo indica la siguiente imagen:
Luego aadimos varios Menu Item al Sub-Menu (uno por cada sitio web a enlazar):
La estructura final del men de opciones debe ser la siguiente:
El cdigo fuente de la clase Proyecto028Activity.java es: package andr oi d. pr oyect o028;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . I nt ent ; i mpor t andr oi d. net . Ur i ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Menu; i mpor t andr oi d. vi ew. MenuI nf l at er ; i mpor t andr oi d. vi ew. MenuI t em; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass Pr oyect o028Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
@Over r i de publ i c bool ean onCr eat eOpt i onsMenu( Menu menu) { MenuI nf l at er i nf l at er =get MenuI nf l at er ( ) ; i nf l at er . i nf l at e( R. menu. menu1, menu) ; r et ur n t r ue; }
@Over r i de publ i c bool ean onOpt i onsI t emSel ect ed( MenuI t emi t em) { I nt ent i ; swi t ch ( i t em. get I t emI d( ) ) { case R. i d. i t em2: i = new I nt ent ( " andr oi d. i nt ent . act i on. VI EW" , Ur i . par se( " ht t p: / / www. googl e. com" ) ) ; st ar t Act i vi t y( i ) ; br eak; case R. i d. i t em3: i = new I nt ent ( " andr oi d. i nt ent . act i on. VI EW" , Ur i . par se( " ht t p: / / www. yahoo. com" ) ) ; st ar t Act i vi t y( i ) ; br eak; case R. i d. i t em4: i = new I nt ent ( " andr oi d. i nt ent . act i on. VI EW" , Ur i . par se( " ht t p: / / www. bi ng. com" ) ) ; st ar t Act i vi t y( i ) ; br eak; case R. i d. i t em5: f i ni sh( ) ; } r et ur n t r ue; } } El mtodo onCreateOptionsMenu es idntico al concepto anterior. En el mtodo onOptionsItemSelected verificamos cual de los MenuItem es seleccionado y procedemos a invocar mediante un Intent al navegador configurado por defecto para el dispositivo.
La visualizacin del submen en tiempo de ejecucin es similar a:
Final del proyecto028.
31 - Men de opciones con conos en los MenuItem
Otra posibilidad es disponer grficos dentro de los MenuItem de nuestro programa.
Problema: Confeccionar una aplicacin que muestre un men con dos opciones: una que active el navegador con YouTube y otra que active Facebook. Disponer un cono para cada MenuItem.
Luego de crear el proyecto procedemos a buscar dos conos representativos de Youtube y Facebook (dos archivos png de 48 pxeles de ancho y alto) y los almacenamos en la carpeta drawable-mdpi.
Luego de refrescar la carpeta debemos tener en nuestro proyecto en dicha carpeta tres archivos:
Procedemos seguidamente a crear el archivo Android XML File (recordemos que lo hacemos presionando el botn derecho del mouse sobre la carpeta res y seleccionando New ->Android XML File)
Creamos un menu llamado menu1 y seleccionamos el RadioButton Menu.
Ahora tenemos que crear los dos Item y especificar las propiedades Title (con el texto que queremos que se muestre) y la propiedad Icon.
Para configurar cada icon procedemos a asignar los valores @drawable/youtube y @drawable/facebook (los nombres coinciden con los nombres de archivos que copiamos a la carpeta drawable)
Nos queda agregar solo la funcionalidad de cada MenuItem: package andr oi d. pr oyect o029;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . I nt ent ; i mpor t andr oi d. net . Ur i ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Menu; i mpor t andr oi d. vi ew. MenuI nf l at er ; i mpor t andr oi d. vi ew. MenuI t em;
publ i c cl ass Pr oyect o029Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
@Over r i de publ i c bool ean onCr eat eOpt i onsMenu( Menu menu) { MenuI nf l at er i nf l at er =get MenuI nf l at er ( ) ; i nf l at er . i nf l at e( R. menu. menu1, menu) ; r et ur n t r ue; }
@Over r i de publ i c bool ean onOpt i onsI t emSel ect ed( MenuI t emi t em) { I nt ent i ; swi t ch ( i t em. get I t emI d( ) ) { case R. i d. i t em1: i = new I nt ent ( " andr oi d. i nt ent . act i on. VI EW" , Ur i . par se( " ht t p: / / www. yout ube. com" ) ) ; st ar t Act i vi t y( i ) ; br eak; case R. i d. i t em2: i = new I nt ent ( " andr oi d. i nt ent . act i on. VI EW" , Ur i . par se( " ht t p: / / www. f acebook. com" ) ) ; st ar t Act i vi t y( i ) ; } r et ur n t r ue; } }
Luego cuando lo ejecutamos podemos observar el cono que se muestra en cada MenuItem:
Final del proyecto029.
32 - Men contextuales
Otra variante de men de opciones son los men contextuales que se pueden asociar a distintos componentes visuales del formulario (TextView, EditText, ListView etc.)
Un men contectual aparece cuando el usuario presiona por un tiempo ms o menos prolongado el control visual.
Problema: Confeccionar una aplicacin que muestre un EditText y asociarle un men contextual que permita cambiar el color de fondo del mismo. El men debe permitir seleccionar entre el rojo, verde y azul.
Primero creamos un proyecto y creamos una interfaz con un control de tipo EditText:
Luego creamos el archivo XML que contendr el men de opciones (presionamos el botn derecho del mouse sobre la carpeta res de nuestro proyecto y seleccionamos New ->Android XML File):
Aparece un dilogo donde debemos indicar el nombre del archivo de recursos a crear (lo llamamos menu1, este es el nombre del archivo XML que se crear en una carpeta llamada menu que depende de la carpeta res) y seleccionamos el RadioButton de men
Ya tenemos una nueva carpeta llamada menu y un archivo llamado menu1.
Creamos las tres opciones del men:
Ahora veamos como asociar el archivo XML donde definimos el men con el cdigo J ava: package andr oi d. pr oyect o030;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. gr aphi cs. Col or ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Cont ext Menu; i mpor t andr oi d. vi ew. Cont ext Menu. Cont ext MenuI nf o; i mpor t andr oi d. vi ew. MenuI nf l at er ; i mpor t andr oi d. vi ew. MenuI t em; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ;
publ i c cl ass Pr oyect o030Act i vi t y ext ends Act i vi t y { Edi t Text et 1; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 1) ; r egi st er For Cont ext Menu( et 1) ; }
@Over r i de publ i c voi d onCr eat eCont ext Menu( Cont ext Menu menu, Vi ew v, Cont ext MenuI nf o menuI nf o) { menu. set Header Ti t l e( " El i j a el col or de f ondo: " ) ; MenuI nf l at er i nf l at er = get MenuI nf l at er ( ) ; i nf l at er . i nf l at e( R. menu. menu1, menu) ; }
@Over r i de publ i c bool ean onCont ext I t emSel ect ed( MenuI t emi t em) { swi t ch ( i t em. get I t emI d( ) ) { case R. i d. i t em1: et 1. set Backgr oundCol or ( Col or . r gb( 255, 0, 0) ) ; br eak; case R. i d. i t em2: et 1. set Backgr oundCol or ( Col or . r gb( 0, 255, 0) ) ; br eak; case R. i d. i t em3: et 1. set Backgr oundCol or ( Col or . r gb( 0, 0, 255) ) ; br eak; } r et ur n t r ue; } }
En el mtodo onCreateContextMenu asociamos el archivo XML llamando al mtodo inflate de la clase MenuInflate. Podemos tambin llamar al mtodo setHeaderTitle para mostrar un ttulo en el men emergente.
@Over r i de publ i c voi d onCr eat eCont ext Menu( Cont ext Menu menu, Vi ew v, Cont ext MenuI nf o menuI nf o) { menu. set Header Ti t l e( " El i j a el col or de f ondo: " ) ; MenuI nf l at er i nf l at er = get MenuI nf l at er ( ) ; i nf l at er . i nf l at e( R. menu. menu1, menu) ; }
Para la captura de eventos de los MenuItem debemos implementar el mtodo onContextItemSelected donde mediante un switch verificamos cual de los MenuItem fue seleccionado y cambiamos el color de fondo del control EditText:
@Over r i de publ i c bool ean onCont ext I t emSel ect ed( MenuI t emi t em) { swi t ch ( i t em. get I t emI d( ) ) { case R. i d. i t em1: et 1. set Backgr oundCol or ( Col or . r gb( 255, 0, 0) ) ; br eak; case R. i d. i t em2: et 1. set Backgr oundCol or ( Col or . r gb( 0, 255, 0) ) ; br eak; case R. i d. i t em3: et 1. set Backgr oundCol or ( Col or . r gb( 0, 0, 255) ) ; br eak; } r et ur n t r ue; }
Final del proyecto030.
33 - AlertDialog simple
El dilogo ms simple que podemos crear con Android en una ventana con un ttulo, un mensaje y un botn para cerrarlo.
Muy til si tenemos que informar al usuario y no queremos que la ventana desaparezca hasta que el usuario presione un botn para ocultar el dilogo.
Problema: Confeccionar una aplicacin que muestre un dilogo cada vez que se inicie la aplicacin informando que el programa que est ejecutando es un programa de prueba y no el completo.
Primero creamos un proyecto llamado: proyecto031
Lo almacenamos en el paquete: android.proyecto031
El cdigo fuente de la aplicacin queda como sigue: package andr oi d. pr oyect o021;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. app. Al er t Di al og; i mpor t andr oi d. os. Bundl e;
publ i c cl ass Pr oyect o031Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Al er t Di al og. Bui l der bui l der = new Al er t Di al og. Bui l der ( t hi s) ; bui l der . set Ti t l e( " I mpor t ant e" ) ; bui l der . set Message( " Est e es un pr ogr ama sol o de pr ueba y no l a ver si n compl et a" ) ; bui l der . set Posi t i veBut t on( " OK" , nul l ) ; bui l der . cr eat e( ) ; bui l der . show( ) ; } }
Como queremos que el dilogo aparezca inmediatamente se arranque la aplicacin procedemos a incorporar el cdigo en el mtodo onCreate.
Primero debemos importar la clase AlertDialog:
i mpor t andr oi d. app. Al er t Di al og;
La clase AlertDialog contiene otra clase llamada Builder que es la que encapsula la creacin de objetos de la clase AlertDialog. Procedemos a definir y crear un objeto de la clase Builder contenida en la clase AlertDialog:
Al er t Di al og. Bui l der bui l der = new Al er t Di al og. Bui l der ( t hi s) ;
Una vez creado el objeto procedemos a llamar al mtodo que define el ttulo a mostrar en el dilogo:
bui l der . set Ti t l e( " I mpor t ant e" ) ;
El mensaje propiamente dicho lo configuramos llamando al mtodo setMessage:
bui l der . set Message( " Est e es un pr ogr ama sol o de pr ueba y no l a ver si n compl et a" ) ;
Mostramos un botn para poder cerrar el dilogo:
bui l der . set Posi t i veBut t on( " OK" , nul l ) ;
Finalmente llamamos al mtodo que crea el dilogo y el que lo visualiza:
bui l der . cr eat e( ) ; bui l der . show( ) ;
La interfaz visual del dilogo en tiempo de ejecucin es:
Final del proyecto031.
34 - AlertDialog con botones de confirmar y cancelar
Problema: Confeccionar una aplicacin que muestre un dilogo cada vez que se inicie la aplicacin informando: "Acepta la ejecucin de este programa en modo prueba?" y dos botones para confirmar o rechazar. En caso que se rechace finalizar la ejecucin del programa.
Primero creamos un proyecto llamado: proyecto032
Lo almacenamos en el paquete: android.proyecto032
El cdigo fuente de la aplicacin queda como sigue: package andr oi d. pr oyect o032;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. app. Al er t Di al og; i mpor t andr oi d. cont ent . Di al ogI nt er f ace; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass Pr oyect o032Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Al er t Di al og. Bui l der di al ogo1 = new Al er t Di al og. Bui l der ( t hi s) ; di al ogo1. set Ti t l e( " I mpor t ant e" ) ; di al ogo1. set Message( " Acept a l a ej ecuci n de est e pr ogr ama en modo pr ueba ?" ) ; di al ogo1. set Cancel abl e( f al se) ; di al ogo1. set Posi t i veBut t on( " Conf i r mar " , new Di al ogI nt er f ace. OnCl i ckLi st ener ( ) { publ i c voi d onCl i ck( Di al ogI nt er f ace di al ogo1, i nt i d) { acept ar ( ) ; } }) ; di al ogo1. set Negat i veBut t on( " Cancel ar " , new Di al ogI nt er f ace. OnCl i ckLi st ener ( ) { publ i c voi d onCl i ck( Di al ogI nt er f ace di al ogo1, i nt i d) { cancel ar ( ) ; } }) ; di al ogo1. show( ) ; }
publ i c voi d acept ar ( ) { Toast t =Toast . makeText ( t hi s, " Bi enveni do a pr obar el pr ogr ama. " , Toast . LENGTH_SHORT) ; t . show( ) ; }
publ i c voi d cancel ar ( ) { f i ni sh( ) ; } }
Creamos un objeto de la clase AlertDialog a travs de la clase Builder:
Al er t Di al og. Bui l der di al ogo1 = new Al er t Di al og. Bui l der ( t hi s) ;
Configuramos el ttulo del dilogo:
di al ogo1. set Ti t l e( " I mpor t ant e" ) ;
Configuramos el mensaje del dilogo:
di al ogo1. set Message( " Acept a l a ej ecuci n de est e pr ogr ama en modo pr ueba ?" ) ;
Evitamos que el dilogo sea salteado por cualquier medio distinto a presionar alguno de los dos botones:
di al ogo1. set Cancel abl e( f al se) ;
Llamamos al mtodo setPositiveButton indicando el texto a mostrar en el botn y la clase annima que capturar el evento clic del botn:
di al ogo1. set Posi t i veBut t on( " Conf i r mar " , new Di al ogI nt er f ace. OnCl i ckLi st ener ( ) { publ i c voi d onCl i ck( Di al ogI nt er f ace di al ogo1, i nt i d) { acept ar ( ) ; } }) ;
De forma similar procedemos con el botn de cancelar:
di al ogo1. set Negat i veBut t on( " Cancel ar " , new Di al ogI nt er f ace. OnCl i ckLi st ener ( ) { publ i c voi d onCl i ck( Di al ogI nt er f ace di al ogo1, i nt i d) { cancel ar ( ) ; } }) ;
Mostramos el dilogo:
di al ogo1. show( ) ;
Definimos los mtodos del Activity que se llamaran desde las clases annimas:
publ i c voi d acept ar ( ) { Toast t =Toast . makeText ( t hi s, " Bi enveni do a pr obar el pr ogr ama. " , Toast . LENGTH_SHORT) ; t . show( ) ; }
publ i c voi d cancel ar ( ) { f i ni sh( ) ; }
La interfaz del dilogo es similar a esta:
Final del proyecto032.
35 - Notificaciones o mensajes mediante la clase Toast
La clase Toast nos permite mostrar un mensaje superpuesto a la ventana por un perodo de tiempo pero sin congelar la aplicacin. Este mensaje no permite interactuar con el usuario (no se pueden ingresar datos, seleccionar botones ni obligar a que se cierre)
Eventualmente se lo puede localizar en distintas partes del dispositivo.
Problema: Confeccionar una aplicacin que muestre una serie de botones y active mensajes de notificaciones con la clase Toast.
Primero creamos un proyecto llamado: proyecto033.
Lo almacenamos en el paquete: android.proyecto033
La interfaz visual a implementar son tres botones:
No olvidemos inicializar la propiedad On Click de cada botn con los mtodos: prueba1, prueba2 y prueba3. El cdigo fuente de la aplicacin queda como sigue: package andr oi d. pr oyect o033;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Gr avi t y; i mpor t andr oi d. vi ew. Layout I nf l at er ; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass Pr oyect o033Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; }
publ i c voi d pr ueba1( Vi ew v) { Toast t oast = Toast . makeText ( t hi s, " Mensaj e 1" , Toast . LENGTH_SHORT) ; t oast . show( ) ; }
publ i c voi d pr ueba2( Vi ew v) { Toast t oast = Toast . makeText ( t hi s, " Mensaj e 2" , Toast . LENGTH_SHORT) ; t oast . set Gr avi t y( Gr avi t y. CENTER_VERTI CAL, 0, 0) ; t oast . show( ) ; }
publ i c voi d pr ueba3( Vi ew v) { Layout I nf l at er i nf l at er = get Layout I nf l at er ( ) ; Vi ew l ayout = i nf l at er . i nf l at e( R. l ayout . t oast 1, nul l ) ; Toast t oast = new Toast ( get Appl i cat i onCont ext ( ) ) ; t oast . set Gr avi t y( Gr avi t y. CENTER_VERTI CAL, 0, 0) ; t oast . set Dur at i on( Toast . LENGTH_LONG) ; t oast . set Vi ew( l ayout ) ; t oast . show( ) ; } }
Para el evento click del primer botn mostramos el mensaje con las estructura ms simple que nos provee la clase Toast. Definimos un objeto de la clase Toast y llamamos al mtodo makeText pasando como parmetro la referencia del Activity, el mensaje a mostrar y una constante indicando si queremos que el mensaje aparezca por un perodo corto o largo de tiempo en la pantalla. Por ltimo llamamos al mtodo show para que se muestre el mensaje:
publ i c voi d pr ueba1( Vi ew v) { Toast t oast = Toast . makeText ( t hi s, " Mensaj e 1" , Toast . LENGTH_SHORT) ; t oast . show( ) ; }
Si queremos ubicar en otra parte de la pantalla debemos llamar al mtodo setGravity e indicar en el primer parmetro una constante (en este ejemplo lo centramos verticalmente)
En el segundo y tercer parmetro de setGravity podemos desplazarlo una cantidad de pxeles hacia derecha o izquierda, arriba o abajo segn indiquemos valores positivos o negativos.
Luego el mtodo completo para este segundo Toast es:
publ i c voi d pr ueba2( Vi ew v) { Toast t oast = Toast . makeText ( t hi s, " Mensaj e 2" , Toast . LENGTH_SHORT) ; t oast . set Gr avi t y( Gr avi t y. CENTER_VERTI CAL, 0, 0) ; t oast . show( ) ; }
Para generar un Toast customizado debemos crear un archivo XML donde creamos visualmente los controles a mostrar, en este ejemplo creamos el siguiente archivo (crear un archivo llamado toast1.xml):
Este recurso luego lo incorporamos en el Toast mediante el siguiente cdigo:
publ i c voi d pr ueba3( Vi ew v) { Layout I nf l at er i nf l at er = get Layout I nf l at er ( ) ; Vi ew l ayout = i nf l at er . i nf l at e( R. l ayout . t oast 1, nul l ) ; Toast t oast = new Toast ( get Appl i cat i onCont ext ( ) ) ; t oast . set Gr avi t y( Gr avi t y. CENTER_VERTI CAL, 0, 0) ; t oast . set Dur at i on( Toast . LENGTH_LONG) ; t oast . set Vi ew( l ayout ) ; t oast . show( ) ; }
Mediante la clase LayoutInflate procedemos a leer el contenido del archivo XML creado anteriormente y lo enlazamos con el toast mediante el mtodo:
t oast . set Vi ew( l ayout ) ;
En pantalla luego el Toast customizado aparece de la siguiente forma:
Final del proyecto033.
36 - Dibujar: graficar un pxel
Problema: Graficar un pxel de color blanco en medio de la pantalla del dispositivo.
Para poder hacer esta simple tarea debemos seguir una serie de pasos:
Creamos un proyecto llamado: proyecto034
Lo almacenamos en el paquete: android.proyecto034
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Ahora codificamos la clase donde se encuentra toda la lgica para encender el pxel: package andr oi d. pr oyect o034;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o034Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { i nt ancho=canvas. get Wi dt h( ) ; i nt al t o=canvas. get Hei ght ( ) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 255, 255) ; canvas. dr awPoi nt ( ancho/ 2, al t o/ 2, pi ncel 1) ; } }
}
Debemos crear una clase que herede de la clase View (todos los controles visuales en Android heredan de esta clase) y sobreescribir el mtodo onDraw. El mtodo onDraw se ejecuta cuando tiene que graficarse. Para acceder a las primitivas grficas hay una clase llamada Canvas que encapsula todo lo relacionado a pintar pxeles, lneas, rectngules etc.:
pr ot ect ed voi d onDr aw( Canvas canvas) { i nt ancho=canvas. get Wi dt h( ) ; i nt al t o=canvas. get Hei ght ( ) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 255, 255) ; canvas. dr awPoi nt ( ancho/ 2, al t o/ 2, pi ncel 1) ; }
Lo primero que hacemos en el mtodo onDraw es obtener el ancho y alto en pxeles del dispositivo mediante los mtodos getWidth() y getHeight() que nos provee la clase Canvas. Seguidamente creamos un objeto de la clase Paint. Llamamos al mtodo setARGB para definir el color del pincel (el primer parmetro indica el valor de transparencia con 255 indicamos que no hay transparencia, luego indicamos la cantidad de rojo, verde y azul.
Por ltimo debemos llamar al mtodo drawPoint que dibuja el pxel en la columna, fila y pincel que le pasamos como parmetros.
Como podemos observar la clase Lienzo hereda de View e implementa el constructor donde llegar la referencia del Activity donde se inserta:
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { i nt ancho=canvas. get Wi dt h( ) ; i nt al t o=canvas. get Hei ght ( ) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 255, 255) ; canvas. dr awPoi nt ( ancho/ 2, al t o/ 2, pi ncel 1) ; } }
Por ltimo en el mtodo onCreate del Activity obtenemos la referencia del LinearLayout que insertamos en el formulario previamente. Creamos un objeto de la clase Lienzo (llamado fondo) y agregamos el objeto fondo al linealLayout llamando al mtodo addView:
publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
Cuando ejecutemos el programa veremos un pxel en medio de la pantalla de color blanco:
Final del proyecto034.
37 - Dibujar: pintar fondo y dibujar lneas
Problema: Pintar el fondo de color amarillo y dibujar una serie de lneas con distintos estilos.
Creamos un proyecto llamado: proyecto035
Lo almacenamos en el paquete: android.proyecto035
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Ahora codificamos la clase donde se encuentra toda la lgica para pintar el fondo y dibujar las lneas: package andr oi d. pr oyect o035;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o035Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 0) ; i nt ancho=canvas. get Wi dt h( ) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ; canvas. dr awLi ne( 0, 30, ancho, 30, pi ncel 1) ; pi ncel 1. set St r okeWi dt h( 4) ; canvas. dr awLi ne( 0, 60, ancho, 60, pi ncel 1) ; } }
}
Veamos el mtodo onDraw donde pintamos el fondo de la componente llamando al mtodo drawRGB donde indicamos la cantidad de rojo, verde a azul:
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 0) ;
Creamos un objeto de la clase paint y definimos el color rojo (recordemos que el primer parmetro indica el valor de la transparencia, si vale 255 es totalmente opaco, con un valor menor el trazo de la lnea tendr transparencia.
El mtodo para graficar una lnea se llama drawLine y tiene como parmetros la columna y fila del punto inicial y el tercer y cuarto parmetro indica la columna y fila del punto final de la lnea (en este ejemplo se dibujar una lnea horizontal en la fila 30 y tendr un ancho que coincide con el ancho del dispositivo), el ltimo parmetro es el objeto de la clase Paint que indica el color de la lnea:
Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ; canvas. dr awLi ne( 0, 30, ancho, 30, pi ncel 1) ;
La siguiente lnea la dibujamos en la fila 60 pero previamente cambiamos el grosor del pincel llamando al mtodo setTrokeWidth indicando que sern 4 pxeles el grosor:
pi ncel 1. set St r okeWi dt h( 4) ; canvas. dr awLi ne( 0, 60, ancho, 60, pi ncel 1) ; La vista previa en el dispositivo ser:
Final del proyecto035.
Problema propuesto
Confeccionar una aplicacin que muestre una hoja en la pantalla similar a esta:
Final del proyecto036.
38 - Dibujar: rectngulos
Problema: Pintar el fondo de color blanco y dibujar una serie de rectngulos con distintos estilos. 1 - Creamos un proyecto llamado: proyecto037
Lo almacenamos en el paquete: android.proyecto037
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Ahora codificamos la clase donde se encuentra toda la lgica: package andr oi d. pr oyect o037;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. gr aphi cs. Pai nt . St yl e; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o037Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 255) ; i nt ancho=canvas. get Wi dt h( ) ; Pai nt pi ncel 1=new Pai nt ( ) ;
pi ncel 1. set ARGB( 255, 255, 0, 0) ; canvas. dr awRect ( 10, 10, ancho- 10, 40, pi ncel 1) ;
pi ncel 1. set St yl e( St yl e. STROKE) ; canvas. dr awRect ( 10, 60, ancho- 10, 90, pi ncel 1) ;
pi ncel 1. set St r okeWi dt h( 3) ; canvas. dr awRect ( 10, 110, ancho- 10, 140, pi ncel 1) ;
} }
}
En el mtodo onDraw de la clase Lienzo procedemos a pintar el fondo de color blanco:
canvas. dr awRGB( 255, 255, 255) ;
Obtenemos el ancho del dispositivo:
i nt ancho=canvas. get Wi dt h( ) ;
Creamos un objeto de la clase Paint:
Pai nt pi ncel 1=new Pai nt ( ) ;
Activamos el color rojo:
pi ncel 1. set ARGB( 255, 255, 0, 0) ;
Dibujamos un rectngulo desde la coordenada columna:10 y fila 10 hasta la columna que coincide con el ancho de la pantalla menos 10 pxeles y la fila 40. Adems le pasamos el pincel a utilizar:
canvas. dr awRect ( 10, 10, ancho- 10, 40, pi ncel 1) ;
Para el siguiente rectngulo configuramos el pincel para que solo pinte el permetro llamando al mtodo setStyle y pasando la constante STROKE:
pi ncel 1. set St yl e( St yl e. STROKE) ; canvas. dr awRect ( 10, 60, ancho- 10, 90, pi ncel 1) ;
Por ltimo dibujamos otro rectngulo que solo se pinta el permetro pero cambiamos el grosor del lapiz llamando al mtodo setStrokeWidth:
pi ncel 1. set St r okeWi dt h( 3) ; canvas. dr awRect ( 10, 110, ancho- 10, 140, pi ncel 1) ;
La vista previa de la aplicacin es:
Final del proyecto037.
39 - Dibujar: crculos
Problema: Pintar el fondo de color blanco y dibujar 10 crculos crecientes desde el medio de la pantalla.
Creamos un proyecto llamado: proyecto038
Lo almacenamos en el paquete: android.proyecto038
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Ahora codificamos la clase donde se encuentra toda la lgica: package andr oi d. pr oyect o038;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. gr aphi cs. Pai nt . St yl e; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o038Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 255) ; i nt ancho=canvas. get Wi dt h( ) ; i nt al t o=canvas. get Hei ght ( ) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ; pi ncel 1. set St yl e( St yl e. STROKE) ; f or ( i nt f =0; f <10; f ++) { canvas. dr awCi r cl e( ancho/ 2, al t o/ 2, f *15, pi ncel 1) ; } } }
}
Pintamos el fondo de blanco y obtenemos el ancho y alto del control:
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 255) ; i nt ancho=canvas. get Wi dt h( ) ; i nt al t o=canvas. get Hei ght ( ) ;
Creamos un objeto de la clase Paint, fijamos el color rojo y mediante setStyle indicamos que solo se debe pintar el permetro:
Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ; pi ncel 1. set St yl e( St yl e. STROKE) ;
Disponemos un for para dibujar los 10 crculos concntricos (indicamos en los dos primeros parmetros el punto central del crculo y en el tercer parmetro el radio del crculo:
f or ( i nt f =0; f <10; f ++) { canvas. dr awCi r cl e( ancho/ 2, al t o/ 2, f *15, pi ncel 1) ; } }
La vista previa de la aplicacin es:
Final del proyecto038.
40 - Dibujar: valos
Problema: Dibujar un valo que ocupe toda la pantalla y un crculo en su interior.
Creamos un proyecto llamado: proyecto039
Lo almacenamos en el paquete: android.proyecto039
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Ahora codificamos la clase donde se encuentra toda la lgica: package andr oi d. pr oyect o039;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. gr aphi cs. Pai nt . St yl e; i mpor t andr oi d. gr aphi cs. Rect F; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. vi ew. Wi ndow; i mpor t andr oi d. vi ew. Wi ndowManager ; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o039Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { r equest Wi ndowFeat ur e( Wi ndow. FEATURE_NO_TI TLE) ; get Wi ndow( ) . set Fl ags( Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN,
Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN) ; super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 255) ; i nt ancho=canvas. get Wi dt h( ) ; i nt al t o=canvas. get Hei ght ( ) ;
Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 0, 0, 0) ; pi ncel 1. set St r okeWi dt h( 5) ; pi ncel 1. set St yl e( St yl e. STROKE) ; Rect F r ect angul o1=new Rect F( 0, 0, ancho, al t o) ; canvas. dr awOval ( r ect angul o1, pi ncel 1) ;
i nt menor ; i f ( ancho<al t o) menor =ancho; el se menor =al t o;
pi ncel 1. set St yl e( St yl e. FI LL) ; pi ncel 1. set ARGB( 255, 255, 255, 0) ; canvas. dr awCi r cl e( ancho/ 2, al t o/ 2, menor / 2, pi ncel 1) ; } }
}
Para ocultar la barra del ttulo y la barra superior debemos hacer lo siguiente en el mtodo onCreate:
publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { r equest Wi ndowFeat ur e( Wi ndow. FEATURE_NO_TI TLE) ; get Wi ndow( ) . set Fl ags( Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN,
Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN) ; super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
En el mtodo onDraw pintamos el fondo de blanco y obtenemos el ancho y alto de la pantalla:
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 255) ; i nt ancho=canvas. get Wi dt h( ) ; i nt al t o=canvas. get Hei ght ( ) ;
Seguidamente creamos el objeto de la clase Paint y configuramos el color, grosor de lnea y estilo:
Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 0, 0, 0) ; pi ncel 1. set St r okeWi dt h( 5) ; pi ncel 1. set St yl e( St yl e. STROKE) ;
Creamos un objeto de la clase RectT pasando como dato la coordenada superior izquierda del valo y la coordenada inferior derecha del mismo (teniendo en cuenta que el valo se dibujar en ese rectngulo imaginario que indicamos con dichas coordenadas):
Rect F r ect angul o1=new Rect F( 0, 0, ancho, al t o) ; canvas. dr awOval ( r ect angul o1, pi ncel 1) ;
Obtenemos el valor menor del ancho y alto del dispositivo:
i nt menor ; i f ( ancho<al t o) menor =ancho; el se menor =al t o;
Configuramos ahora el pincel para dibujar el crculo y lo dibujamos:
pi ncel 1. set St yl e( St yl e. FI LL) ; pi ncel 1. set ARGB( 255, 255, 255, 0) ; canvas. dr awCi r cl e( ancho/ 2, al t o/ 2, menor / 2, pi ncel 1) ; }
La vista previa de la aplicacin es:
Final del proyecto039.
41 - Dibujar: texto
Otra recurso que nos permite la clase Canvas es el de graficar texto.
Creamos un proyecto llamado: proyecto040
Lo almacenamos en el paquete: android.proyecto040
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Ahora codificamos la clase donde se encuentra toda la lgica: package andr oi d. pr oyect o040;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. gr aphi cs. Typef ace; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. vi ew. Wi ndow; i mpor t andr oi d. vi ew. Wi ndowManager ; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o040Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { r equest Wi ndowFeat ur e( Wi ndow. FEATURE_NO_TI TLE) ; get Wi ndow( ) . set Fl ags( Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN,
Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN) ; super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 0, 0, 255) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ; pi ncel 1. set Text Si ze( 30) ; pi ncel 1. set Typef ace( Typef ace. SERI F) ; canvas. dr awText ( " Hol a Mundo ( SERI F) " , 0, 70, pi ncel 1) ; pi ncel 1. set Typef ace( Typef ace. SANS_SERI F) ; canvas. dr awText ( " Hol a Mundo ( SANS SERI F) " , 0, 100, pi ncel 1) ; pi ncel 1. set Typef ace( Typef ace. MONOSPACE) ; canvas. dr awText ( " Hol a Mundo ( MONOSPACE) " , 0, 140, pi ncel 1) ; Typef ace t f =Typef ace. cr eat e( Typef ace. SERI F, Typef ace. I TALI C) ; pi ncel 1. set Typef ace( t f ) ; canvas. dr awText ( " Hol a Mundo ( SERI F I TALI C) " , 0, 180, pi ncel 1) ; t f =Typef ace. cr eat e( Typef ace. SERI F, Typef ace. I TALI C | Typef ace. BOLD) ; pi ncel 1. set Typef ace( t f ) ; canvas. dr awText ( " Hol a Mundo ( SERI F I TALI C BOLD) " , 0, 220, pi ncel 1) ; } }
}
Para graficar texto disponemos del mtodo drawText que nos permite imprimir un String en una determinada columna, fila con un determinado pincel que podemos definir su color:
Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ;
El tamao de la letra:
pi ncel 1. set Text Si ze( 30) ;
El estilo de la letra:
pi ncel 1. set Typef ace( Typef ace. SERI F) ;
La interfaz del programa es:
Final del proyecto040.
42 - Dibujar: texto con fuentes externas
Podemos confeccionar aplicaciones e incorporar fuentes True Type externas. Para ello implementaremos una aplicacin que muestre un texto con una fuente externa.
Creamos un proyecto llamado: proyecto041
Lo almacenamos en el paquete: android.proyecto041
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Procedemos ahora a descargar una fuente del sitio Creamundo y copiamos el archivo de la fuente a la carpeta assets como se muestra:
Ahora codificamos la clase donde se encuentra toda la lgica: package andr oi d. pr oyect o041;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. gr aphi cs. Typef ace; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. vi ew. Wi ndow; i mpor t andr oi d. vi ew. Wi ndowManager ; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o041Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { r equest Wi ndowFeat ur e( Wi ndow. FEATURE_NO_TI TLE) ; get Wi ndow( ) . set Fl ags( Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN,
Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN) ; super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 255) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 0, 0, 0) ; pi ncel 1. set Text Si ze( 30) ; Typef ace f ace = Typef ace. cr eat eFr omAsset ( get Asset s( ) , " Act i on Man Shaded. t t f " ) ; pi ncel 1. set Typef ace( f ace) ; canvas. dr awText ( " Hol a Mundo" , 0, 120, pi ncel 1) ; } }
}
En el mtodo onDraw procedemos a crear una fuente llamando al mtodo createFromAsset e indicando el nombre del archivo que descargamos de internet (disponga en el segundo parmetro el nombre del archivo que eligi y descarg de internet):
Typef ace f ace = Typef ace. cr eat eFr omAsset ( get Asset s( ) , " Act i on Man Shaded. t t f " ) ; pi ncel 1. set Typef ace( f ace) ;
La interfaz del programa es:
Final del proyecto041.
43 - Dibujar: texto sobre un camino Si queremos disponer texto no no est horizontal debemos crear un camino indicando los puntos donde pasar el texto.
Creamos un proyecto llamado: proyecto042
Lo almacenamos en el paquete: android.proyecto042
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Ahora codificamos la clase donde se encuentra toda la lgica: package andr oi d. pr oyect o042;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. gr aphi cs. Pat h; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. vi ew. Wi ndow; i mpor t andr oi d. vi ew. Wi ndowManager ; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o042Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { r equest Wi ndowFeat ur e( Wi ndow. FEATURE_NO_TI TLE) ; get Wi ndow( ) . set Fl ags( Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN,
Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN) ; super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 0, 0, 255) ; i nt al t o=canvas. get Hei ght ( ) ;
Pat h cami no = new Pat h( ) ; cami no. moveTo( 0, al t o/ 2) ; cami no. l i neTo( 40, al t o/ 2- 30) ; cami no. l i neTo( 80, al t o/ 2- 60) ; cami no. l i neTo( 120, al t o/ 2- 90) ; cami no. l i neTo( 160, al t o/ 2- 120) ; cami no. l i neTo( 220, al t o/ 2- 150) ; cami no. l i neTo( 280, al t o/ 2- 180) ; cami no. l i neTo( 340, al t o/ 2- 210) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ; pi ncel 1. set Text Si ze( 30) ; canvas. dr awText OnPat h( " Hol a Mundo Hol a Mundo" , cami no, 0, 0, pi ncel 1) ; } }
}
Creamos un objeto de la clase Path e indicamos el primer punto del camino llamando al mtodo moveTo:
Pat h cami no = new Pat h( ) ; cami no. moveTo( 0, al t o/ 2) ;
Luego indicamos todos los otros puntos en forma consecutiva llamando al mtodo lineTo:
cami no. l i neTo( 40, al t o/ 2- 30) ; cami no. l i neTo( 80, al t o/ 2- 60) ; cami no. l i neTo( 120, al t o/ 2- 90) ; cami no. l i neTo( 160, al t o/ 2- 120) ; cami no. l i neTo( 220, al t o/ 2- 150) ; cami no. l i neTo( 280, al t o/ 2- 180) ; cami no. l i neTo( 340, al t o/ 2- 210) ;
Luego para graficar el texto llamamos al mtodo drawTextOnPath y le pasamos en el segundo parmetro la referencia del objeto de tipo Path:
canvas. dr awText OnPat h( " Hol a Mundo Hol a Mundo" , cami no, 0, 0, pi ncel 1) ;
La salida del programa es:
Final del proyecto042.
La vista previa de la aplicacin es:
Final del proyecto044.
44 - Dibujar: una imagen
Para mostrar un archivo jpg, png etc. disponemos el la clase Canvas de un mtodo llamado drawBitmap.
Problema: Mostrar el contenido de un archivo jpg centrado en la pantalla sabiendo que tiene un tamao de 250 pxeles de ancho por 200 de alto.
Creamos un proyecto llamado: proyecto043
Lo almacenamos en el paquete: android.proyecto043
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Descargar de internet una imagen y redimensionarla a 250*200 pxeles. Copiar dicho archivo a la carpeta res/drawable-hdpi de nuestro proyecto (actualizar desde el Eclipse dicha carpeta):
Ahora codificamos la clase donde se encuentra toda la lgica: package andr oi d. pr oyect o043;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Bi t map; i mpor t andr oi d. gr aphi cs. Bi t mapFact or y; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. vi ew. Wi ndow; i mpor t andr oi d. vi ew. Wi ndowManager ; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o043Act i vi t y ext ends Act i vi t y { / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { r equest Wi ndowFeat ur e( Wi ndow. FEATURE_NO_TI TLE) ; get Wi ndow( ) . set Fl ags( Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN,
Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN) ; super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; Li enzo f ondo=new Li enzo( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 0, 0, 255) ; i nt ancho=canvas. get Wi dt h( ) ; i nt al t o=canvas. get Hei ght ( ) ; Bi t map bmp=Bi t mapFact or y. decodeResour ce( get Resour ces( ) , R. dr awabl e. i magen1) ; canvas. dr awBi t map( bmp, ( ancho- 250) / 2, ( al t o- 200) / 2, nul l ) ; } }
} Para recuperar la imagen del archivo de la carpeta res/drawable-hdpi debemos utilizar el mtodo decodeResource:
Bi t map bmp=Bi t mapFact or y. decodeResour ce( get Resour ces( ) , R. dr awabl e. i magen1) ;
Una vez que tenemos creado el objeto de la clase Bitmap procedemos a posicionar la imagen en forma centrada en la pantalla del dispositivo:
canvas. dr awBi t map( bmp, ( ancho- 250) / 2, ( al t o- 200) / 2, nul l ) ;
La vista previa de la aplicacin es:
Final del proyecto043.
45 - Evento touch: dibujar un crculo
Una actividad fundamental es poder detectar cuando el usuario selecciona o toca la pantalla tctil. Problema: Desarrollar un programa que dibuje un crculo en la coordenada 100,100. Cuando se presione otra parte de la pantalla tctil proceder a trasladar el crculo a dicha coordenada.
1 - Creamos un proyecto llamado: proyecto044
Lo almacenamos en el paquete: android.proyecto044
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a insertar un objeto de la clase LinearLayout (vertical):
Ahora codificamos la clase donde se encuentra toda la lgica para capturar el evento onTouch: package andr oi d. pr oyect o044;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Mot i onEvent ; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. vi ew. Vi ew. OnTouchLi st ener ; i mpor t andr oi d. wi dget . Li near Layout ;
publ i c cl ass Pr oyect o044Act i vi t y ext ends Act i vi t y i mpl ement s OnTouchLi st ener { pr i vat e i nt cor x, cor y; pr i vat e Li enzo f ondo; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l i near Layout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; cor x=100; cor y=100; f ondo=new Li enzo( t hi s) ; f ondo. set OnTouchLi st ener ( t hi s) ; l i near Layout . addVi ew( f ondo) ; }
publ i c bool ean onTouch( Vi ew v, Mot i onEvent event ) { cor x=( i nt ) event . get X( ) ; cor y=( i nt ) event . get Y( ) ; f ondo. i nval i dat e( ) ; r et ur n t r ue; }
cl ass Li enzo ext ends Vi ew {
publ i c Li enzo( Cont ext cont ext ) { super ( cont ext ) ; }
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 0) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ; pi ncel 1. set St r okeWi dt h( 4) ; pi ncel 1. set St yl e( Pai nt . St yl e. STROKE) ; canvas. dr awCi r cl e( cor x, cor y, 20, pi ncel 1) ; } }
}
La clase que captura el evento onTouch debe implementar la interface OnTouchListener (con esto indicamos que la clase debe implementar el mtodo onTouch:
publ i c cl ass Pr oyect o044Act i vi t y ext ends Act i vi t y i mpl ement s OnTouchLi st ener {
Definimos como atributos la coordenada donde se debe dibujar el crculo y la referencia al objeto de la clase Lienzo:
pr i vat e i nt cor x, cor y; pr i vat e Li enzo f ondo;
En el mtodo onCreate del Activity inicializamos los tres atributos de la clase y mediante el mtodo setOnTouchListener indicamos que la propia clase capturar el evento onTouch del objeto fondo:
cor x=100; cor y=100; f ondo=new Li enzo( t hi s) ; f ondo. set OnTouchLi st ener ( t hi s) ; l i near Layout . addVi ew( f ondo) ;
El mtodo onTouch es el que implementamos de la clase OnTouchListener. En este mtodo mediante el objeto event obtenemos la coordenada x e y donde el usuario seleccion con el dedo y procedemos a llamar al mtodo invalidate para que vuelva a pintarse el control fondo (el mtodo invalidate borra el contendio del objeto de la clase Lienzo y vuelve a ejecutarse el mtodo onDraw):
publ i c bool ean onTouch( Vi ew v, Mot i onEvent event ) { cor x=( i nt ) event . get X( ) ; cor y=( i nt ) event . get Y( ) ; f ondo. i nval i dat e( ) ; r et ur n t r ue; }
El mtodo onDraw pinta el fondo de amarillo, crea un objeto de la clase Paint y procede a dibujar un crculo en las coordenadas indicadas por los atributos corx y cory:
pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 255, 255, 0) ; Pai nt pi ncel 1=new Pai nt ( ) ; pi ncel 1. set ARGB( 255, 255, 0, 0) ; pi ncel 1. set St r okeWi dt h( 4) ; pi ncel 1. set St yl e( Pai nt . St yl e. STROKE) ; canvas. dr awCi r cl e( cor x, cor y, 20, pi ncel 1) ; }
La vista previa de la aplicacin es:
Final del proyecto044.
46 - Evento touch: juego del buscaminas
Problema: Implementar el juego del Buscaminas. Crear una grilla de 8*8 celdas. 1 - Creamos un proyecto llamado: BuscaMinas
Lo almacenamos en el paquete: android.BuscaMinas
Borramos el TextView que agrega automticamente el plug-in de Eclipse y procedemos a inicializar la propiedad Id del LinearLayout con el valor LinearLayout1:
Luego codificamos las clases BuscaMinasActivity y Casilla: package andr oi d. buscami nas;
publ i c cl ass Casi l l a { publ i c i nt x, y, ancho; publ i c i nt cont eni do=0; publ i c bool ean dest apado=f al se; publ i c voi d f i j ar xy( i nt x, i nt y, i nt ancho) { t hi s. x=x; t hi s. y=y; t hi s. ancho=ancho; }
publ i c bool ean dent r o( i nt xx, i nt yy) { i f ( xx>=t hi s. x && xx<=t hi s. x+ancho && yy>=t hi s. y && yy<=t hi s. y+ancho) r et ur n t r ue; el se r et ur n f al se; } }
Y la clase: package andr oi d. buscami nas;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. cont ent . Cont ext ; i mpor t andr oi d. gr aphi cs. Canvas; i mpor t andr oi d. gr aphi cs. Pai nt ; i mpor t andr oi d. gr aphi cs. Typef ace; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Mot i onEvent ; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. vi ew. Vi ew. OnTouchLi st ener ; i mpor t andr oi d. vi ew. Wi ndow; i mpor t andr oi d. vi ew. Wi ndowManager ; i mpor t andr oi d. wi dget . Li near Layout ; i mpor t andr oi d. wi dget . Toast ;
publ i c cl ass BuscaMi nasAct i vi t y ext ends Act i vi t y i mpl ement s OnTouchLi st ener {
pr i vat e Tabl er o f ondo; i nt x, y; pr i vat e Casi l l a[ ] [ ] casi l l as; pr i vat e bool ean act i vo=t r ue; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { r equest Wi ndowFeat ur e( Wi ndow. FEATURE_NO_TI TLE) ; get Wi ndow( ) . set Fl ags( Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN, Wi ndowManager . Layout Par ams. FLAG_FULLSCREEN) ;
super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ;
Li near Layout l ayout = ( Li near Layout ) f i ndVi ewByI d( R. i d. l i near Layout 1) ; f ondo=new Tabl er o( t hi s) ; f ondo. set OnTouchLi st ener ( t hi s) ; l ayout . addVi ew( f ondo) ; casi l l as=new Casi l l a[ 8] [ 8] ; f or ( i nt f =0; f <8; f ++) { f or ( i nt c=0; c<8; c++) { casi l l as[ f ] [ c] =new Casi l l a( ) ; } } t hi s. di sponer Bombas( ) ; t hi s. cont ar BombasPer i met r o( ) ; }
publ i c voi d pr esi onado( Vi ew v) { casi l l as=new Casi l l a[ 8] [ 8] ; f or ( i nt f =0; f <8; f ++) { f or ( i nt c=0; c<8; c++) { casi l l as[ f ] [ c] =new Casi l l a( ) ; } } t hi s. di sponer Bombas( ) ; t hi s. cont ar BombasPer i met r o( ) ; act i vo=t r ue;
f ondo. i nval i dat e( ) ; }
@Over r i de publ i c bool ean onTouch( Vi ew v, Mot i onEvent event ) { i f ( act i vo) f or ( i nt f =0; f <8; f ++) { f or ( i nt c=0; c<8; c++) { i f ( casi l l as[ f ] [ c] . dent r o( ( i nt ) event . get X( ) , ( i nt ) event . get Y( ) ) ) { casi l l as[ f ] [ c] . dest apado=t r ue; i f ( casi l l as[ f ] [ c] . cont eni do==80) {
Toast . makeText ( t hi s, " Booooooooommmmmmmmmmmm" , Toast . LENGTH_LONG) . show( ) ; act i vo=f al se; } el se i f ( casi l l as[ f ] [ c] . cont eni do==0) r ecor r er ( f , c) ; f ondo. i nval i dat e( ) ; } } } i f ( gano( ) && act i vo) { Toast . makeText ( t hi s, " Ganast e" , Toast . LENGTH_LONG) . show( ) ; act i vo=f al se; }
r et ur n t r ue; } cl ass Tabl er o ext ends Vi ew {
publ i c Tabl er o( Cont ext cont ext ) { super ( cont ext ) ; } pr ot ect ed voi d onDr aw( Canvas canvas) { canvas. dr awRGB( 0, 0, 0 ) ; i nt ancho=0; i f ( canvas. get Wi dt h( ) <canvas. get Hei ght ( ) ) ancho=f ondo. get Wi dt h( ) ; el se ancho=f ondo. get Hei ght ( ) ; i nt anchocua=ancho/ 8; Pai nt pai nt =new Pai nt ( ) ; pai nt . set Text Si ze( 20) ; Pai nt pai nt 2=new Pai nt ( ) ; pai nt 2. set Text Si ze( 20) ; pai nt 2. set Typef ace( Typef ace. DEFAULT_BOLD) ; pai nt 2. set ARGB( 255, 0, 0, 255) ; Pai nt pai nt l i nea1=new Pai nt ( ) ; pai nt l i nea1. set ARGB( 255, 255, 255, 255) ; i nt f i l aact =0; f or ( i nt f =0; f <8; f ++) { f or ( i nt c=0; c<8; c++) { casi l l as[ f ] [ c] . f i j ar xy( c*anchocua, f i l aact , anchocua) ; i f ( casi l l as[ f ] [ c] . dest apado==f al se) pai nt . set ARGB( 153, 204, 204, 204) ; el se pai nt . set ARGB( 255, 153, 153, 153) ; canvas. dr awRect ( c*anchocua, f i l aact , c*anchocua+anchocua- 2, f i l aact +anchocua- 2, pai nt ) ; / / l i nea bl anca canvas. dr awLi ne( c*anchocua, f i l aact , c*anchocua+anchocua, f i l aact , pai nt l i nea1) ; canvas. dr awLi ne( c*anchocua+anchocua- 1, f i l aact , c*anchocua+anchocua- 1, f i l aact +anchocua, pai nt l i nea1) ;
i f ( casi l l as[ f ] [ c] . cont eni do>=1 && casi l l as[ f ] [ c] . cont eni do<=8 && casi l l as[ f ] [ c] . dest apado)
canvas. dr awText ( St r i ng. val ueOf ( casi l l as[ f ] [ c] . cont eni do) , c*anchocua+( anchocua/ 2) - 8, f i l aact +anchocua/ 2, pai nt 2) ;
i f ( casi l l as[ f ] [ c] . cont eni do==80 && casi l l as[ f ] [ c] . dest apado) { Pai nt bomba=new Pai nt ( ) ; bomba. set ARGB( 255, 255, 0, 0) ; canvas. dr awCi r cl e( c*anchocua+( anchocua/ 2) , f i l aact +( anchocua/ 2) , 8, bomba) ; }
} f i l aact =f i l aact +anchocua; } } }
pr i vat e voi d di sponer Bombas ( ) { i nt cant i dad = 8; do { i nt f i l a = ( i nt ) ( Mat h. r andom( ) * 8) ; i nt col umna = ( i nt ) ( Mat h. r andom( ) * 8) ; i f ( casi l l as[ f i l a] [ col umna] . cont eni do == 0) { casi l l as [ f i l a] [ col umna] . cont eni do=80; cant i dad- - ; } } whi l e ( cant i dad ! = 0) ; }
pr i vat e bool ean gano( ) { i nt cant =0; f or ( i nt f = 0 ; f < 8 ; f ++) f or ( i nt c = 0 ; c < 8 ; c++) i f ( casi l l as [ f ] [ c] . dest apado) cant ++; i f ( cant ==56) r et ur n t r ue; el se r et ur n f al se; }
pr i vat e voi d cont ar BombasPer i met r o ( ) { f or ( i nt f = 0 ; f < 8 ; f ++) { f or ( i nt c = 0 ; c < 8 ; c++) { i f ( casi l l as [ f ] [ c] . cont eni do==0) { i nt cant = cont ar Coor denada ( f , c) ; casi l l as [ f ] [ c] . cont eni do=cant ; } } } }
i nt cont ar Coor denada ( i nt f i l a, i nt col umna) { i nt t ot al = 0; i f ( f i l a - 1 >= 0 && col umna - 1 >= 0) { i f ( casi l l as [ f i l a - 1] [ col umna - 1] . cont eni do == 80) t ot al ++; } i f ( f i l a - 1 >= 0) { i f ( casi l l as [ f i l a - 1] [ col umna] . cont eni do == 80) t ot al ++; } i f ( f i l a - 1 >= 0 && col umna + 1 < 8) { i f ( casi l l as [ f i l a - 1] [ col umna + 1] . cont eni do == 80) t ot al ++; }
i f ( col umna + 1 < 8) { i f ( casi l l as [ f i l a] [ col umna + 1] . cont eni do == 80) t ot al ++; } i f ( f i l a + 1 < 8 && col umna + 1 < 8) { i f ( casi l l as [ f i l a + 1] [ col umna + 1] . cont eni do == 80) t ot al ++; }
i f ( f i l a + 1 < 8) { i f ( casi l l as [ f i l a + 1] [ col umna] . cont eni do == 80) t ot al ++; } i f ( f i l a + 1 < 8 && col umna - 1 >= 0) { i f ( casi l l as [ f i l a + 1] [ col umna - 1] . cont eni do == 80) t ot al ++; } i f ( col umna - 1 >= 0) { i f ( casi l l as [ f i l a] [ col umna - 1] . cont eni do == 80) t ot al ++; } r et ur n t ot al ; }
pr i vat e voi d r ecor r er ( i nt f i l , i nt col ) { i f ( f i l >= 0 && f i l < 8 && col >= 0 && col < 8) { i f ( casi l l as [ f i l ] [ col ] . cont eni do==0) { casi l l as [ f i l ] [ col ] . dest apado=t r ue; casi l l as [ f i l ] [ col ] . cont eni do=50; r ecor r er ( f i l , col + 1) ; r ecor r er ( f i l , col - 1) ; r ecor r er ( f i l + 1, col ) ; r ecor r er ( f i l - 1, col ) ; r ecor r er ( f i l - 1, col - 1) ; r ecor r er ( f i l - 1, col + 1) ; r ecor r er ( f i l + 1, col + 1) ; r ecor r er ( f i l + 1, col - 1) ; } el se i f ( casi l l as [ f i l ] [ col ] . cont eni do>=1 && casi l l as [ f i l ] [ col ] . cont eni do<=8) { casi l l as [ f i l ] [ col ] . dest apado=t r ue; } } } }
La interfaz visual de la aplicacin es:
Final del BuscaMinas.
47 - Archivo strings.xml
El archivo strings.xml se utiliza para almacenar todas las constantes de cadenas de caracteres que se necesitan en un programa (por ejemplo las etiquetas de los objetos Button, los textos fijos de los controles TextView y todos los controles que muestran un texto fijo en el dispositivo)
La idea fundamental es tener todos los mensajes que muestra nuestra aplicacin en un archivo (strings.xml)
Ya veremos en el prximo concepto que uno de las ventajas que presenta esta agrupacin de string es la posibilidad de facilitar la implementacin de aplicaciones en mltiples idiomas.
Problema: Crear un proyecto que solicite la carga de dos valores. Mediante dos RadioButton permitir seleccionar si queremos sumar o restar. Cuando se presione un botn mostrar en un TextView el resultado de la operacin.
Creamos un proyecto llamado: proyecto045
Lo almacenamos en el paquete: android.proyecto045
El Plugin de Eclipse nos crea automticamente el archivo strings.xml en la carpeta values que se encuentra en la carpeta res:
Si vemos en su interior podemos ver que ya define dos string llamados app_name y hello:
Lo que se encuentra entre las marcas string es lo que se visualizar, por ejemplo en la constante hello se almacena el valor "Hello World, Proyecto045Activity!". En este archivo crearemos todas las constantes a incluir en nuestro programa. Si vemos en la parte inferior de la ventana donde se visualiza el archivo xml hay una pestaa llamada Resource que nos permite ingresar las distintas constantes de una forma visual:
Creamos primero la interfaz visual disponiendo dos controles de tipo EditText, un RadioGroup con dos RadioButton, un Button y un TextView donde se muestra el resultado de la operacin:
Ahora si crearemos los mensajes que mostrarn los dos RadioButton y el Button. Para esto seleccionamos el archivo strings y procedemos a crear las tres constantes:
Una vez que tenemos abierto el archivo strings.xml en modo "Resources" procedemos a presionar el botn "Add..." y seleccionamos "String":
Creamos los nombres de las constantes y los valores, por ejemplo para el mensaje que mostrar el primer RadioButton llamamos la constante con el nombre "radiosuma" y el valor que almacena es "Sumar"
De forma similar creamos las constantes "radioresta" con el valor "Restar" y el boton para operar lo llamamos "botonoperacion" con el valor "Operar". Si seleccionamos la pestaa strings.xml luego podemos ver las tres constantes que hemos creado (podemos borrar la constante que cre el plugin de Eclipse "hello" ya que no lo utilizaremos):
Ahora debemos asociar estas constantes a los controles visuales. Seleccionamos el archivo main.xml y seleccionamos primero el primer RadioButton y buscamos la propiedad Text, presionamos el botn que aparece a la derecha:
En este dilogo seleccionamos la constante de string que acabamos de crear ("radiosuma"):
Ahora tenemos asociada la constante "radiosuma" con la propiedad text del control RadioButton. Lo mismo podramos haber hecho esto escribiendo en la propiedad @string/radiosuma (@string lo utilizamos para indicar que el siguiente dato despus de la barra se trata de una constante definida en el archivo strings.xml)
Utilizar el dilogo de seleccin de recursos nos facilita no tener que recordar todas las constantes.
Lo mismo hacemos para asociar las constantes para el segundo RadioButton y el Button de operar. Es decir las propiedades text del radio1 debe quedar con el valor "@string/radioresta" y el valor de la propiedad text del objeto button1 debe ser "@string/botonoperacion"
Como vemos cuando asociamos las propiedades text de los controles con las constantes automticamente vemos en pantalla que los textos de los controles se actualizan con los valores almacenados en dichas constantes.
Para que funcione nuestro programa inicializamos la propiedad On click del Button con el mtodo que sumar o restar:
El cdigo fuente del programa ser: package andr oi d. pr oyect o045;
i mpor t andr oi d. app. Act i vi t y; i mpor t andr oi d. os. Bundl e; i mpor t andr oi d. vi ew. Vi ew; i mpor t andr oi d. wi dget . Edi t Text ; i mpor t andr oi d. wi dget . Radi oBut t on; i mpor t andr oi d. wi dget . Text Vi ew;
publ i c cl ass Pr oyect o045Act i vi t y ext ends Act i vi t y { Edi t Text et 1, et 2; Radi oBut t on r b1, r b2; Text Vi ew t v1; / ** Cal l ed when t he act i vi t y i s f i r st cr eat ed. */ @Over r i de publ i c voi d onCr eat e( Bundl e savedI nst anceSt at e) { super . onCr eat e( savedI nst anceSt at e) ; set Cont ent Vi ew( R. l ayout . mai n) ; et 1=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 1) ; et 2=( Edi t Text ) f i ndVi ewByI d( R. i d. edi t Text 2) ; r b1=( Radi oBut t on) f i ndVi ewByI d( R. i d. r adi o0) ; r b2=( Radi oBut t on) f i ndVi ewByI d( R. i d. r adi o1) ; t v1=( Text Vi ew) f i ndVi ewByI d( R. i d. t ext Vi ew1) ; }
publ i c voi d oper ar ( Vi ew v) { i nt v1=I nt eger . par seI nt ( et 1. get Text ( ) . t oSt r i ng( ) ) ; i nt v2=I nt eger . par seI nt ( et 2. get Text ( ) . t oSt r i ng( ) ) ; i f ( r b1. i sChecked( ) ) { i nt suma=v1+v2; t v1. set Text ( St r i ng. val ueOf ( suma) ) ; } el se i f ( r b2. i sChecked( ) ) { i nt r est a=v1- v2; t v1. set Text ( St r i ng. val ueOf ( r est a) ) ; } } }
El resultado final del programa en el dispositivo es:
48 - Internacionalizacin y archivo strings.xml
La internacionalizacin de un programa en Android se resuelve implementando varios archivos strings.xml (uno por cada idioma que necesitemos implementar)
Problema: Modificar el proyecto025 de tal manera que muestre su interfaz en castellano o ingles segn la configuracin del idioma seleccionado en el dispositivo.
Crearemos primero una nueva carpeta llamada values-en (las abreviaturas para los distintos lenguajes los podemos ver en la pgina ISO 639-1 Code (segunda columna)
Es decir creamos otra carpeta con el mismo nombre (values) ms un guin y la extensin del lenguaje a implementar:
Creamos un archivo xml llamado strings.xml en la carpeta que acabamos de crear y copiamos todo el archivo strings.xml de la otra carpeta values. Procedemos a traducir los valores almacenados en cada string:
Solamente con esto ya tenemos nuestra aplicacin funcionando en dos idiomas. Para probar debemos acceder al emulador de Android y configurarlo en ingls (tecla home ->tecla menu -> configuracin >Idioma y teclado >Seleccionar idioma ->"English (United Stated)
Luego de esto lanzamos la aplicacin y deberemos ver la interfaz con los string que configuramos en el archivo strings.xml de la carpeta values-en:
49 - Localizacin y archivo strings.xml Hemos visto si queremos tener traducida nuestra aplicacin a varios idiomas debemos utilizar el concepto de internacionalizacin. Pero hay muchos casos donde queremos hilar ms fino. Por ejemplo el ingles de Estados Unidos no es exactamente igual que el ingles de Inglaterra o de Autralia. Para estas situaciones podemos crear varios archivos strings.xml para distintas localidades que tienen el mismo idioma.
Problema: Modificar el proyecto025 de tal manera que muestre su interfaz no solo para el idioma por defecto (espaol) e ingles, sino para el portugus de Brasil y el portugus de Portugal.
Las abreviaturas para los distintos lenguajes los podemos ver en la pgina ISO 639-1 Code (segunda columna) y para obtener las distintas regiones utilizamos la tabla ISO 3166-1-alpha-2
Luego debemos crear una carpeta con el nombre values, luego un guin y el cdigo de internacionalizacin, finalmente otro guin el caracter r y finalmente el cdigo de regin.
En nuestro problemas crearemos dos directorios llamados:
val ues- pt - r BR val ues- pt - r PT
Luego de crear estos dos directorios copiaremos el archivo strings.xml de la carpeta values y procederemos a traducirlo al portugus de Brasil y al portugus de Portugal.
Luego de crear las dos carpetas copiar el archivo strings.xml y proceder a traducirlo primero al portugus de Brasil y luego en la otra carpeta traducirlo al portugus de Portugal, solo nos resta compilar y probar la aplicacin.
Para probar debemos acceder al emulador de Android y configurarlo en portugus de Brasil (tecla home ->tecla menu ->configuracin >Idioma y teclado >Seleccionar idioma ->"Portugus (Brasil)
Seguidamente ejecutar la aplicacin y ver como resultado que tenemos los mensajes que definimos en el archivo strings.xml asociado con el portugus de Brasil:
Lo mismo podemos luego configurar el idioma portugus de Portugal y obtener como resultado en una nueva ejecucin del programa: