6.9.7.-
Programación en Android – Actividad Configuración
VII – Diálogos
En este capítulo seguiremos
añadiendo y modificando el código para la
ActividadConfiguracion.java,
de forma que al terminar este tutorial ya podremos añadir la
fecha de nacimiento y ver el control DatePicker en acción.
Pero
primeramente vamos a hablar un poco sobre los diálogos.
Los
diálogos son una manera de aprovechar el espacio disponible en
la pantalla del teléfono sin saturar el interfaz, ya que los
datos se piden en una ventana emergente, con lo que nos evitamos
muchos cambios de actividad, evitando así saturar el SO.
Normalmente son pequeñas ventanas que se muestran delante de
nuestra actividad y que toman el control de la interacción con
el usuario.
Tipos
de diálogos
La
clase base para la creación de diálogos es Dialog,
aunque normalmente no se hace una instancia directamente de esta
clase, sino de alguna de las siguientes subclases:
Tipo
de diálogo
|
Descripción
|
Dialog
(Clase Base)
|
Es la
clase base para la generación de diálogos. Las
demás subclases heredan de esta.
|
AlertDialog
|
Es un
diálogo que puede manejar hasta 3 botones y/o una lista de
elementos seleccionables que pueden incluir botones
circulares o de checkeo (Radio buttons
y checkboxes).
|
CharacterPickerDialog
|
Diálogo
utilizado para seleccionar carácteres especiales.
|
DatePickerDialog
|
Un
diálogo que permite al usuario escoger una fecha.
|
ProgressDialog
|
Es un
diálogo que muestra una rueda o una barra de progreso. Es
una extensión de AlertDialog, por lo tanto también
soporta botones.
|
TimePickerDialog
|
Un
diálogo que permite al usuario escoger una hora.
|
Custom
Dialogs
(Diálogos a medida) |
Es una
forma de crear diálogos propios o a medida. Se puede hacer
extendiendo la clase Dialog o alguna de las anteriores, y
definiendo un nuevo diseño (layout).
|
Mostrando
un Diálogo
Los diálogos siempre son
creados como parte de una actividad. Normalmente se crean en el
método de retrollamada (callback) onCreateDialog(int).
Al utilizar este callback,
el SO Android maneja
automáticamente el estado de cada uno de los diálogos y
los enlaza a una Activity, haciendo que dicha Activity sea la
propietaria del mismo. Asimismo el diálogo también
hereda algunas particularidades de la Activity a la que pertenece,
como puede ser el menú de opciones definido para la actividad.
Los
diálogos también se pueden crear fuera del método
onCreateDialog(int),
y entonces no se enganchan a ninguna actividad. Si queremos
posteriormente hacer que pertenezca a una actividad determinada,
debemos utilizar el método setOwnerActivity(Activity).
Para
mostrar el diálogo se utiliza la función
showDialog(int),
pasándole como
argumento un int
que es el identificador único del diálogo a mostrar.
Cuando
se muestra por primera vez, Android llama a onCreateDialog(int),
que es dónde debemos instanciar el diálogo. A esta
retrollamada se le pasa el mismo identificador de diálogo que
se le pasó al método showDialog(int).
Después de crear el
diálogo debemos retornar el objeto (diálogo) al
finalizar el método.
Antes
de que se muestre el diálogo, Android también llama a
un método opcional: onPrepareDialog(int,
Dialog). Este método
sólo nos hará falta en caso de que queramos cambiar las
propiedades del diálogo cada vez que se abra. Este método
se llama siempre
y cada una de las veces
que se abra un diálogo,
mientras el método onCreateDialog(int)
sólo se llama la
primera vez que se abre
un diálogo. En caso de que no hallamos creado este método
(onPrepareDialog) entonces
el diálogo seguirá igual que la última vez que
se abrió.
La
mejor forma de definir las retrollamadas (callback)
a los métodos onCreateDialog(int) y
onPrepareDialog(int, Dialog),
es en una sentencia de tipo switch,
en la cuál se comprobará
el parámetro de identificación del diálogo que
se le ha pasado al método. Cada sentencia case
deberá comprobar
un único identificador de de diálogo para después
crear y definir dicho diálogo.
Descartando
un diálogo
Cuando
queramos desechar un diálogo, debemos llamar al método
dismissDialog(int) si
lo hacemos desde la Activity o simplemente dismiss()
si lo hacemos desde el propio diálogo.
Si
el diálogo ha sido creado a través del método
onCreateDialog(int),
entonces aunque descartemos el diálogo, su estado permanece
retenido por la Activity. Si decidimos que no vamos a necesitarlo
más o que es importante que se borre su estado, entonces
debemos llamar al método removeDialog(int),
que quitará todas las referencias internas al objeto y en caso
de que se este mostrando lo descartará.
Si
se desea que la aplicación realice algún procedimiento
cuando se desecha el diálogo, entonces debemos enlazarlo con
un listener (oyente) OnDismiss. Para ello debemos crear primero el
interfaz DialogInterface.OnDismissListener,
que contendrá un único método:
onDismiss(DialogInterface),
que será llamado cuando se descarte el diálogo.
Después sólo debemos pasar nuestra implementación
de OnDismissListener
al método setOnDismissListener().
Los
diálogos también se pueden cancelar,
este caso ocurre cuando el usuario pulsa el botón atrás
para cerrar el diálogo o si el diálogo llama
explícitamente al método cancel().
Cuándo se cancela un diálogo todavía se llama a
OnDismissListener,
pero si queremos diferenciar si ha sido cancelado expresamente en vez
de desechado con normalidad, entonces debemos de registrar el
listener DialogInterface.OnCancellListener
con setOnCancellListener().
Resumen
Vamos a ver una tabla con un resumen
de algunas de las opciones:
Ciclo
de vida del diálogo
|
|
Función
|
Descripción
|
showDialog
|
Para
mostrar una instancia del diálogo. Se le pasa un
identificador del diálogo.
|
dismissDialog
|
Para
dejar de mostrar el diálogo, rechazarlo o descartarlo. El
diálogo permanece en el "cache" de diálogos
de la aplicación, si se vuelve a llamar a showDialog
entonces el diálogo se carga desde el cache.
|
removeDialog
|
Para
quitar un diálogo del cache. Ya no se guarda para usos
futuros, en caso de llamar posteriormente a showDialog entonces el
diálogo tiene que volver a ser creado.
|
Definiendo
el diálogo
|
|
Función
|
Descripción
|
onCreateDialog
|
Los
diálogos deben ser definidos de antemano y cada uno tiene
un identificador (int). Se debe sobreescribir este método
para que devuelva la instancia correcta para el identificador
pasado como parámetro. Sólo se llama una vez para
crear el diálogo.
|
Inicializando
el diálogo
|
|
Función
|
Descripción
|
onPrepareDialog
|
Método
opcional que tenemos que sobreescribir en caso de que queramos
alterar el contenido del diálogo. Se llama cada vez que se
llama al método showDialog.
|
Ahora que tenemos un poco de
información sobre los diálogos, vamos a proceder a
añadir uno a nuestra ActividadConfiguración.
Añadiendo un diálogo
DatePickerDialog
Para añadir un diálogo
a nuestra actividad, debemos realizar una serie de pasos:
1.-Debemos crear un identificador
único para nuestro diálogo.
2.-Debemos de implementar el método
onCreateDialog(). Y dentro de él añadir una
clase interna que contendrá el listener para
OnDateSetListener.
3.-Debemos de implementar el método
onPrepareDialog(), ya que alteraremos los datos iniciales
mostrados en el mismo.
4.-Debemos cambiar el método
onClickBoton_PonerFecha, para que muestre nuestro diálogo.
5.-Realizar otros pequeños
cambios al código.
#1 – Creando un
identificador para nuestro diálogo
Para añadir un identificador
para nuestro diálogo, simplemente añadimos una variable
miembro a nuestra clase ActividadConfiguración:
/**Identificador
para el diálogo de la fecha */
static
final
int
ID_DIALOGO_FECHA
= 0;
|
Este identificador está fuera
de cualquier método. Aprovechamos también para añadir
una variable miembro, que será la que tenga el valor de la
fecha de nacimiento como un long:
/**
*
El valor aunque no se inicialize será 0L
*
Utilizamos long en vez del wrapper (Long) ya que no vamos a
*utilizar sus funciones.
*
En caso de querer utilizarlas se utilizaria:Long fecha =
*Long.valueOf(mFechaDeNacimiento);
*/
long
mFechaDeNacimiento;
|
#2 – Implementando el
método onCreateDialog y el listener OnDateSetListener
Vamos a implementar el método
onCreateDialog, para ello abrimos el menú pinchando con el
botón derecho sobre el código y vamos a Codigo
fuente->Alterar temporalmente/implementar métodos, y
ahí marcamos el método onCreateDialog (int id).
Este método quedaría como sigue:
protected
Dialog
onCreateDialog(int
id)
{
/**Obtenemos
la referencia al textView de la fecha de nacimiento:*/
final
TextView
TV_Fecha = (TextView)
findViewById(R.id.tV_EstadoFecha);
/**
* Variable para obtener el día actual
*/
Calendar
fechaDeHoy = Calendar.getInstance();
//-----------------------------------------------
//Listener
para el onDateSet
class
fecha_OnDateSetListener
implements
DatePickerDialog.OnDateSetListener
{
/**
OJO:
El orden que tienen los parámetros en DatePicker
* no es el mismo que el orden que se utiliza en Time.set
* En Time.set no se verifican los valores, con lo cual en caso
* de no ser correctos nos fallará la conversión de
toMillis
*/
@Override
public
void
onDateSet(DatePicker
view, int
año, int
mes, int
dia)
{
//Creamos
una variable que contendrá la fecha de nacimiento entrada
por el usuario.
Time
fechaDeNacimiento = new
Time();
//Hacemos
que dicha fecha coja los valores que hay en el Datepicker (dia,
mes, año)
fechaDeNacimiento.set(dia,
mes, año);
//fechaDeNacimiento.normalize(true);
//TODO:
Deberíamos comparar estos valores con la fecha actual:
//Convertimos
la fecha a un long (a millisegundos)
mFechaDeNacimiento
= fechaDeNacimiento.toMillis(true);
//Cambiamos
el TextView de la fecha para que ponga este valor.
TV_Fecha.setText(DateFormat.format(
res.getString(R.string.formatoFecha),
mFechaDeNacimiento));
//TODO
Deberíamos guardar la fecha.
TV_Fecha.setTextColor(res
.getColor(R.color.color_EditText_Configuracion));
}
}
//------------------------------------------------
switch
(id)
{
case
ID_DIALOGO_FECHA:
{
//No
son necesarios los corchetes. Es una costumbre para verlo mejor.
//TODO:
AQui retornamos un DatePickerDialog
//Creamos
el DatePickerDialog
DatePickerDialog
dialogoFecha = new
DatePickerDialog(this,
new
fecha_OnDateSetListener(),
fechaDeHoy.get(Calendar.YEAR),
fechaDeHoy.get(Calendar.MONTH),
fechaDeHoy.get(Calendar.DAY_OF_MONTH));
//Devolvemos
la instancia del diálogo.
return
dialogoFecha;
}
}
return
null;
}
|
Hemos creado una clase interna para
el listener de DatePickerDialog.OnDateSetListener, pero
podíamos haberla creado anónima. En ese listener lo
que hacemos es coger los datos del diálogo, convertirlos a un
long para almacenarlos en la variable mFechaDeNacimiento
y después ponemos el TextView
de la fecha con el formato adecuado.
Asimismo podemos ver que en la
sentencia switch hacemos uso de la clase Calendar
para obtener la fecha actual que es la que se le para al diálogo
para ser mostrada en caso de que no sea válida o que no
tengamos una fecha.
#3 – Implementación
del método onPrepareDialog
Ahora debemos seguir los mismos
pasos que antes para añadir la implementación del
método onPrepareDialog, el cuál quedará de la
siguiente manera:
/**
*
onPrepareDialog: Este método inicializa los diálogos
* a sus valores
iniciales.
*/
@Override
protected
void
onPrepareDialog(int
id, Dialog
dialog)
{
//
TODO
Auto-generated method stub
super.onPrepareDialog(id,
dialog);
switch
(id)
{
case
ID_DIALOGO_FECHA:
{
//Añadimos
el código para controlar la aparición de este
diálogo
/**
Estos tres ints guardaran la fecha actual o la guardada para
* cuando se llame al diálogo con updateDate
*/
int
dia, mes, año;
/**
Diálogo DatePicker
* (dialog): viene como parámetro para este método
*/
DatePickerDialog
dialogoFecha = (DatePickerDialog)
dialog;
//Comprobamos
si hay una fecha en la variable: mFechaDeNacimiento
if
(mFechaDeNacimiento
!= 0)
{
//Si
hay Fecha: ponemos en el diálogo los valores de la fecha:
/**#1
Creamos un objeto para poder descomponer el Long en
* Dia, mes, hora...
*/
Time
fechaDeNacimiento = new
Time();
/**
Y la inicializamos*/
fechaDeNacimiento.set(mFechaDeNacimiento);
//Actualizamos
la fecha para cuando hagamos la llamada
dia
= fechaDeNacimiento.monthDay;
mes
= fechaDeNacimiento.month;
año
= fechaDeNacimiento.year;
}
else
{
//En
caso de que no exista una fecha, ponemos la fecha actual:
//Obtenemos
una instancia del calendario:
Calendar
fechaDeHoy = Calendar.getInstance();
dia
= fechaDeHoy.get(Calendar.DAY_OF_MONTH);
mes
= fechaDeHoy.get(Calendar.MONTH);
año
= fechaDeHoy.get(Calendar.YEAR);
}
//Ahora
actualizamos la fecha del DatePicker:
dialogoFecha.updateDate(año,
mes, dia);
//Y
volvemos
return;
}
}
}
|
En este método también
comprobamos si está siendo llamado para nuestro diálogo,
y en ese caso comprobamos el valor de mFechaDeNacimiento para
ver si tiene un valor válido, en caso de ser así
cogemos los valores del día, mes y año, en caso
contrario cogemos los valores del día actual, y despues
llamamos al método updateDate del diálogo.
#4 – Modificar el método
onClickBoton_PonerFecha
Alteramos este método y
quitamos el mensaje toast que teníamos y ponemos la siguiente
línea:
showDialog(ID_DIALOGO_FECHA);
|
Ahora cada vez que se pulse en este
botón se mostrará nuestro diálogo.
#5 – Otros cambios al
código
También debemos de realizar
cambios en el método inicializaFecha,
de forma que coja el valor de mFechaDeNacimiento para mostrar en la
TextView.
Y
por último debemos modificar el método onPause
para que grabe el dato:
mEditorFicheroConf.putLong(PREFERENCIAS_JUEGO_FECHA_NACIMIENTO,
mFechaDeNacimiento);
|
Y ya deberíamos de poder
ejecutar el programa y ver como funciona nuestro diálogo.
El
código para el proyecto está en el siguiente enlace:
aquí.
Ver.
1.0 – Revisión 25/04/2012
No hay comentarios:
Publicar un comentario