Вы находитесь на странице: 1из 28

hermosaprogramacion.com http://www.hermosaprogramacion.

com/2015/06/como-crear-dialogos-en-android/

¿Como Crear Diálogos En Android?


Como ya has de suponer, los diálogos son elementos en la interfaz de Android que se sobreponen a las
actividades para exigir la confirmación de una acción o el ingreso de datos.

Se caracterizan por interrumpir una tarea del usuario, alterando el foco de la aplicación e invitándolo de forma
intrusiva a que vea información, decida ante una circunstancia crítica o especifique datos.

Por ejemplo…

Puedes usar un diálogo para recordar la importancia de borrar un elemento de la interfaz antes de continuar con
la tarea.

También puedes crear un layout personalizado para el login del


usuario al aplicativo.

Son vitales para seleccionar una preferencia:

O incluso si deseas crear formularios para la edición o inserción


de datos:

Como ves, existen varios tipos de propósito para los diálogos.


Así que el objetivo de este artículo es explicar cómo usar
cada uno de las categorías existentes de modo que toda
situación quede aclarada.

Comenzaremos con el uso de la clase DialogFragment


para instanciar los diálogos. Aunque Dialog es la clase que
genera la interfaz, DialogFragment es quien permite
controlar los eventos de forma fluida. Por ello no se
recomienda crear objetos de clase base.

Luego estudiaremos la subclase AlertDialog para


construir diálogos con título, cuerpo y botones de acción.

A través de ella generaremos diálogos de confirmación,


diálogos de selección múltiple, date picker, time pickers y
diálogos personalizados.

Cada uno de los ejemplos ha sido incluido dentro de la siguiente aplicación:

Para descargar el proyecto en Android Studio completo, puedes usar el siguiente botón:

Descargar Código

Crear Diálogos De Alerta Con La Clase AlertDialog En Android


Un diálogo de alerta es aquel que está diseñado para mostrar un título, un mensaje o cuerpo y hasta 3 botones
de confirmación en su zona de acción.

En los botones podremos ver acciones familiares como lo son la aceptación (Botón positivo) que determina que el
usuario está de acuerdo con la acción. La cancelación (Botón negativo) para evitar la realización de una acción, y
la neutralidad (Botón neutro) para determinar que aún no se está listo para proseguir o cancelar la acción.
Un diálogo de alerta se representa con la clase AlertDialog. En su construcción debes usar un elemento
auxiliar llamado Builder, el cual te ayudará a definir las
partes del diálogo con gran facilidad y sus eventos de
respuesta para los botones.

Builder te permitirá fabricar las características del diálogo


a través de métodos set*(). Los más frecuentes son:

setTitle(): Asigna una cadena al título del


diálogo.
setMessage(): Setea el mensaje que deseas
transmitir en el contenido.
setPossitiveButton(): Crea una instancia del
botón de confirmación. El primer parámetro que
recibe es el texto del botón y el segundo una escucha
OnClickListener para determinar qué acción se
tomará al ser presionado.
setNegativeButton(): Hace exactamente lo
mismo que setPossitiveButton() pero para el botón
de decisión negativa.
setNeutralButton(): Genera una escucha para el
botón neutral. Al igual que los dos métodos anteriores,
recibe el nombre y la escucha.

Con estos métodos ya podemos definir un Builder que


implemente un diálogo simple con título, mensaje y dos
botones…

/**
* Crea un diálogo de alerta sencillo
* @return Nuevo diálogo
*/
public AlertDialog createSimpleDialog() {
AlertDialog.Builder builder = new
AlertDialog.Builder(getActivity());

builder.setTitle("Titulo")
.setMessage("El Mensaje para el
usuario")
.setPositiveButton("OK",
new
DialogInterface.OnClickListener() {
@Override
public void
onClick(DialogInterface dialog, int which) {

listener.onPossitiveButtonClick();
}
})
.setNegativeButton("CANCELAR",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listener.onNegativeButtonClick();
}
});

return builder.create();
}

Luego de setear las características, materializas el diálogo a


través de create(). Puedes crear un método que retorne en
la instancia ya creada para organizar tu código.

Crear Un AlertDialog Con Lista

También es posible crear un diálogo con una lista de elementos que permita algún tipo de selección por parte del
usuario. Donde es posible crear una lista de elementos comunes, una lista de radio buttons o una lista de
checkeo múltiple.

Crear Dialogo con lista simple

Si quieres crear una lista simple usa el método setItems() en vez de setMessage(). Este método recibe un
arreglo de cadenas que permita definir las etiquetas de los elementos y una escucha OnClickListener para
decidir que sucede…

/**
* Crea un Diálogo con una lista de selección simple
*
* @return La instancia del diálogo
*/
public AlertDialog createSingleListDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

final CharSequence[] items = new CharSequence[3];

items[0] = "Naranja";
items[1] = "Mango";
items[2] = "Banano";

builder.setTitle("Diálogo De Lista")
.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(
getActivity(),
"Seleccionaste:" + items[which],
Toast.LENGTH_SHORT)
.show();
}
});

return builder.create();
}

Para saber que ítem fue presionado consulta el parámetro which. Este te indicará el índice seleccionado del
array.
Crear dialogo con lista de radio buttons

Ahora creemos una lista con radio buttons. Esta vez


usaremos el método setSingleChoiceItems(), el cual
también recibe un array de caracteres, el índice del radio
seleccionado y una escucha para el manejo de los eventos:

/**
* Crea un diálogo con una lista de radios
*
* @return Diálogo
*/
public AlertDialog createRadioListDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

final CharSequence[] items = new CharSequence[3];

items[0] = "Soltero/a";
items[1] = "Casado/a";
items[2] = "Divorciado/a";

builder.setTitle("Estado Civil")
.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(
getActivity(),
"Seleccionaste: " + items[which],
Toast.LENGTH_SHORT)
.show();
}
});

return builder.create();
}

Con ello se tendría un resultado así:

Crear dialogo con lista de múltiple selección de


checkboxes

La implementación de un diálogo con checklists requiere el


uso del método setMultipleChoiceItems(). Al igual que
los otros tipos de lista, este recibe un array con las etiquetas
de cada elemento y una escucha para los eventos.
Adicionalmente tiene un parámetro para indicar que
checkboxes están seleccionado.

/**
* Crea un diálogo con una lista de checkboxes
* de selección multiple
*
* @return Diálogo
*/
public AlertDialog createMultipleListDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

final ArrayList itemsSeleccionados = new ArrayList();

CharSequence[] items = new CharSequence[3];

items[0] = "Desarrollo Android";


items[1] = "Diseño De Bases De Datos";
items[2] = "Pruebas Unitarias";

builder.setTitle("Intereses")
.setMultiChoiceItems(items, null, new
DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean
isChecked) {
if (isChecked) {
// Guardar indice seleccionado
itemsSeleccionados.add(which);
Toast.makeText(
getActivity(),
"Checks seleccionados:(" +
itemsSeleccionados.size() + ")",
Toast.LENGTH_SHORT)
.show();
} else if (itemsSeleccionados.contains(which)) {
// Remover indice sin selección
itemsSeleccionados.remove(Integer.valueOf(which));
}
}
});

return builder.create();
}

En este caso puedes tomar la selección de varias casillas. Para contarlas usa un pequeño array para añadir
aquellos que estén marcados (esto lo sabes con el parámetro isChecked). De lo contrario retiralos del array
cuando no lo estén.

Crear un diálogo personalizado

La implementación de un dialogo personalizado requiere la


creación previa de un layout que ocupe el contenido del
dialogo.

Normalmente puedes usar algunas de las medidas estándar


de diseño Material Design que se muestra en el apartado de
diálogos:
Como ves, el contenido se ve muy bien distribuido si usas 24dp para el padding de contorno. También se usa
20dp entre el título y el contenido.

Desde el punto de vista técnico, se requiere que la definición xml sea inflada a través del método inflate() del
componente LayoutInflater. Esto lo puede hacer al obtener una instancia con getLayoutInflater().

Luego seteas el view construido, con el método setView() de AlertDialog.Builder.

Por ejemplo…
El siguiente layout muestra un formulario común donde se
pide el inicio de sesión de nuestro usuario o la creación
de una cuenta. Como ves, el contenido tiene distribución
vertical de los campos y botones coloridos en distintas
posiciones.

dialog_signin.xml

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


<RelativeLayout

xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:padding="@dimen/dialog_body">

<TextView
android:id="@+id/info_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:gravity="center"
android:paddingBottom="@dimen/padding_between"
android:paddingTop="@dimen/padding_between"
android:text="@string/info_text"
android:textAppearance="?android:attr/textAppearanceSmall" />

<Button
android:id="@+id/crear_boton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/info_text"
android:layout_centerHorizontal="true"
android:paddingBottom="@dimen/button_padding"
android:paddingTop="@dimen/button_padding"
android:text="@string/crear_boton"
android:textColor="@android:color/white" />

<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/crear_boton"
android:layout_marginBottom="@dimen/padding_between"
android:layout_marginTop="@dimen/padding_between"
android:background="#C8C9CB" />

<EditText
android:id="@+id/nombre_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/divider"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/normal_padding"
android:background="@drawable/edit_text_border"
android:ems="10"
android:hint="@string/nombre_input"
android:inputType="textPersonName"
android:padding="@dimen/edit_text_padding"
android:textAppearance="?android:attr/textAppearanceSmall" />

<EditText
android:id="@+id/contrasena_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/nombre_input"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/padding_between"
android:layout_marginTop="@dimen/normal_padding"
android:background="@drawable/edit_text_border"
android:ems="10"
android:hint="@string/contrasena_input"
android:inputType="textPassword"
android:padding="@dimen/edit_text_padding"
android:textAppearance="?android:attr/textAppearanceSmall" />

<CheckBox
android:id="@+id/recordar_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/contrasena_input"
android:layout_alignStart="@+id/contrasena_input"
android:layout_below="@+id/contrasena_input"
android:checked="false"
android:text="@string/recordar_check" />
<TextView
android:id="@+id/olvidar_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/contrasena_input"
android:layout_alignRight="@+id/contrasena_input"
android:layout_below="@+id/recordar_check"
android:paddingTop="@dimen/padding_between"
android:text="@string/olvidar_text"
android:textAppearance="?android:attr/textAppearanceSmall" />

<Button
android:id="@+id/entrar_boton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:paddingBottom="@dimen/button_padding"
android:paddingTop="@dimen/button_padding"
android:text="@string/entrar_boton"
android:textColor="@android:color/white" />
</RelativeLayout>

Para aplicar este contenido sobre nuestro diálogo debemos llevar a cabo los pasos anteriormente descritos…

/**
* Crea un diálogo con personalizado para comportarse
* como formulario de login
*
* @return Diálogo
*/
public AlertDialog createLoginDialogo() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

LayoutInflater inflater = getActivity().getLayoutInflater();

View v = inflater.inflate(R.layout.dialog_signin, null);

builder.setView(v);

Button signup = (Button) v.findViewById(R.id.crear_boton);


Button signin = (Button) v.findViewById(R.id.entrar_boton);

signup.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Crear Cuenta...
dismiss();
}
}
);

signin.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Loguear...
dismiss();
}
}

);

return builder.create();
}

Un proceso sencillo. Cada botón tendrá su evento correspondiente a las acciones deseadas (crear cuenta y
loguear).

Este ejemplo no ha sido ajustado para landscape. Sin embargo, es importante que optimices tus diálogos
personalizados para esta variación.

Creación De Diálogos Con La Clase DialogFragment


DialogFragment es un fragmento que contiene un dialogo en su layout por defecto. Usar esta clase permite
mantener optimizados los estados del diálogo, lo que permite controlar el ciclo de vida de forma oportuna.

Si deseas soportar el uso de DialogFragment hasta la versión 1.6 (API 4) recuerda usar la librería de soporte
con la siguiente directiva:

import android.support.v4.app.DialogFragment;

Para implementarlo simplemente crea una clase y extiéndela de DialogFragment. Luego sobrescribe el método
onCreateDialog() para que retorne en la instancia de alguna subclase de Dialog.

Por ejemplo…

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;

/**
* Fragmento con diálogo básico
*/
public class SimpleDialog extends DialogFragment {

public SimpleDialog() {
}

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return createSimpleDialog();
}
/**
* Crea un diálogo de alerta sencillo
* @return Nuevo diálogo
*/
public AlertDialog createSimpleDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

builder.setTitle("Titulo")
.setMessage("El Mensaje para el usuario")
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which)
{
// Acciones
}
})
.setNegativeButton("CANCELAR",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which)
{
// Acciones
}
});

return builder.create();
}
}

Pero… ¿Cómo mostrar el diálogo?

Debes crear una nueva instancia del DialogFragment en la actividad o fragmento donde desees que se
proyecte. A continuación llamas al método show(), el cual se encarga de mostrar el diálogo contenido en el
fragmento.

// En algún lugar de tu actividad


new SimpleDialog().show(getSupportFragmentManager(), "SimpleDialog");

show() recibe la instancia del FragmentManager y la etiqueta descriptiva del diálogo para su identificación.
Para conseguir el fragment manager simplemente usa el método getSupportFragmentManager(). Si lo vas a
mostrar en un fragmento, usa solo getFragmentManager().

Enviar eventos desde un DialogFragment hacia su Actividad Contenedora


Si deseas pasar los eventos que ocurren en el diálogo hacia una actividad debes acudir a una interfaz de
comunicación que permita compartir los métodos de acción.

A continuación te dejo los pasos a seguir:

Paso #1: Declara una interfaz dentro del DialogFragment. La declaración de la interfaz debe tener definido un
método por cada acción que reciba el diálogo.

Si deseas procesar en la actividad los métodos del botón positivo y el negativo, entonces creas una interfaz con
dos métodos respectivos:
public interface OnSimpleDialogListener {
void onPossitiveButtonClick();// Eventos Botón Positivo
void onNegativeButtonClick();// Eventos Botón Negativo
}

Paso #2: Declarar un atributo del tipo de la interfaz para conseguir la instancia directa de la actividad.

// Interfaz de comunicación
OnSimpleDialogListener listener;

Paso #3: Comprobar que la actividad ha implementado la interfaz podemos usar el método onAttach().
Recuerda que este recibe la instancia de la actividad contenedora del fragmento. Simplemente asignas la
actividad a la instancia de la interfaz.

Si este proceso no es posible, entonces lanzas una excepción del tipo ClassCastException.

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);

try {
listener = (OnSimpleDialogListener) activity;

} catch (ClassCastException e) {
throw new ClassCastException(
activity.toString() +
" no implementó OnSimpleDialogListener");

}
}

Paso #4: Invocar los métodos de la interfaz en las secciones del diálogo donde deseamos implicar a la actividad.

.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listener.onPossitiveButtonClick();
}
})
.setNegativeButton("CANCELAR",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listener.onNegativeButtonClick();
}
});

Paso #5: Implementar sobre la actividad contenedora, la interfaz declarada en el fragmento.

public class MainActivity extends AppCompatActivity implements


OnSimpleDialogListener{

//...
}
Paso #6: Sobrescribir dentro de la actividad los métodos de la interfaz, con las acciones que requieras.

@Override
public void onPossitiveButtonClick() {
// Acciones
}

@Override
public void onNegativeButtonClick() {
// Acciones
}

¿Cómo Comunicar Un DialogFragment Con Un Fragment?


Una de las formas para comunicar un fragmento de diálogo y un fragmento común, es tomar la actividad
contenedora como puente entre ambos. Es decir, enviar los eventos desde el DialogFragment hacia la
actividad y luego desde la actividad hacia el Fragment.

Esta convención es recomendada, ya que en la documentación oficial de Android Developers se menciona que
no se deben comunicar dos fragmentos directamente. Quizás porque las esperanzas de vida de los fragmentos
pueden variar, así que es mejor asegurar su independencia de transmisión.

Veamos este ejemplo para entender mejor…

Supón que tienes un fragmento sencillo con un text view y un botón. La idea es que al presionar el botón, se
despliegue el diálogo de lista simple que hemos construido con anterioridad.

Y una vez seleccionada la opción, se actualizará el texto a través de la actividad.

Lo primero es crear un DialogFragment que tenga tres opciones. Para este ejemplo usaré el mensaje “¿Qué
fruta te gusta más?” y añadiré tres opciones: “Naranja”, “Mango” y “Banano”:

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;

/**
* Fragmento con diálogo de lista simple
*/
public class SimpleListDialog extends DialogFragment {

public interface OnSetTitleListener{


void setTitle(String title);
}

OnSetTitleListener listener;

public SimpleListDialog() {
}

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return createSingleListDialog();
}

/**
* Crea un Diálogo con una lista de selección simple
*
* @return La instancia del diálogo
*/
public AlertDialog createSingleListDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

final CharSequence[] items = new CharSequence[3];

items[0] = "Naranja";
items[1] = "Mango";
items[2] = "Banano";

builder.setTitle("¿Qué fruta te gusta más?")


.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listener.setTitle((String) items[which]);
}
});

return builder.create();
}

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);

try {
listener = (OnSetTitleListener) activity;

} catch (ClassCastException e) {
throw new ClassCastException(
activity.toString() +
" no implementó OnSetTitleListener");

}
}

Como ves, la escucha de comunicación onSetTitleListener provee un método llamado setTitle() para
gestionar la selección del usuario. Justo en el momento que el usuario presiona (método onClick()), se envía
hacia la actividad la cadena contenida en items[which].

Ahora en la actividad principal, se implementará la interfaz y se sobrescribirá el método de implementación:

public class MainActivity extends AppCompatActivity implements


SimpleListDialog.OnSetTitleListener {
// Dentro de una actividad...
@Override
public void setTitle(String title) {
FragmentoObjetivo fragment =
getSupportFragmentManager().findFragmentByTag("FragmentoObjetivo");

if(fragment!=null){
fragment.setTitle(title);
}else{
// Reporta el error...
}
}
}

Al recibir el evento, debes llamar a la instancia del fragmento al que necesitas pasar los resultados. Para ello
llamas al administrador de fragmentos y usas el método findFragmentById() o findFragmentByTag().

El primero obtiene la instancia del fragmento con el id pasado como parámetro y el segundo obtiene el fragmento
que contiene la etiqueta especificada.

Con eso ya puedes llamar el método hipotético setTitle() del fragmento y comunicar la fruta preferida del
usuario en el text view.

Crear Un Diálogo Con DatePicker


Un DatePicker o selector de fecha es un view elaborado para permitir al usuario seleccionar una fecha
configurable. Donde puede elegir el año, el mes y el día respectivamente.
Normalmente se puede setear de forma estática sobre un
layout. Si deseas encontrarlo en Android Studio, ve a la
pestaña de diseño, luego a la paleta y selecciona
“DatePicker” en la categoría “Date & Time”:

Pero nuestro objetivo no es usarlo de esa forma. Lo que


necesitamos es crear un diálogo que se sobreponga ante
el layout para no consumir espacio.

Esto se logra a través de la subclase


DatePickerDialog, la cual representa un diálogo con
un selector de fechas en su interior.

Al igual que como hemos hecho hasta ahora con los


demás diálogos, creamos un DialogFragment para que
actué como envoltura. Para ello se retorna en una
instancia de DatePickerDialog en el método
onCreateDialog().

DateDialog.java

import android.annotation.TargetApi;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.os.Build;
import android.os.Bundle;
import
android.support.v4.app.DialogFragment;

import java.util.Calendar;

/**
* Fragmento con un diálogo de elección de fechas
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class DateDialog extends DialogFragment {

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
// Obtener fecha actual
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);

// Retornar en nueva instancia del dialogo


selector de fecha
return new DatePickerDialog(
getActivity(),
(DatePickerDialog.OnDateSetListener) getActivity(),
year,
month,
day);
}
}

Para la construcción solo se requiere añadir la fecha por defecto con que se mostrará el diálogo. La clase
Calendar puede ayudarte a obtener la fecha actual por si deseas usarla.

Ahora, si quieres leer los eventos de selección de fecha, usa la interfaz


DatePickerDialog.onDateSetListener sobre la actividad contenedora. Esta provee el método callback
onDateSet() para la determinar las acciones que se realizarán con la fecha seleccionada.

Con ello puedes sobrescribir el método en tu actividad y realizar la acción que desees. En el siguiente ejemplo
despliego la fecha elegida en un Toast:

@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
Toast.makeText(
this,
"Fecha: " + year + "-" + monthOfYear + "-" + dayOfMonth,
Toast.LENGTH_LONG)
.show();

Crear Diálogo Con Un TimePicker En Su Interior


El TimePicker o selector de tiempo es muy similar al DatePicker. Este permite seleccionar el tiempo a través
de una configuración de las horas y minutos.
Si deseas añadirlo a través del editor de Android Studio
debes dirigirte a la paleta, encontrar la categoría “Date &
Time” y luego arrastrar el objeto “TimePicker”:

Ahora, para añadirlo a un diálogo haremos el mismo


procedimiento anterior. Usaremos la clase análoga
TimePickerDialog con un DialogFragment.

TimeDialog.java

import android.annotation.TargetApi;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Build;
import android.os.Bundle;
import
android.support.v4.app.DialogFragment;
import android.text.format.DateFormat;

import java.util.Calendar;

/**
* Fragmento con un diálogo de elección de
tiempos
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class TimeDialog extends
DialogFragment {

@Override
public Dialog onCreateDialog(Bundle
savedInstanceState) {
// Iniciar con el tiempo actual
final Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);

// Retornar en nueva instancia del dialogo


selector de tiempo
return new TimePickerDialog(
getActivity(),
(TimePickerDialog.OnTimeSetListener)
getActivity(),
hour,
minute,
DateFormat.is24HourFormat(getActivity()));
}

El TimePickerDialog se construye con el tiempo actual detectado con ayuda de la clase Calendar. Donde su
constructor recibe los siguientes parámetros:

context: Es el contexto donde se relacionará el diálogo. En este caso llamamos a la actividad


contenedora con getActivity().
callBack: Es la interfaz por la cual se comunicará el diálogo. En este caso pusimos la actividad
contenedora, ya que esta implementará la interfaz OnTimeSetListener.
hourOfDay: La hora inicial.
minute: Los minutos iniciales.
is24HourView: Determina si el time picker tendrá un formato de 24 horas o AM/PM. Para esto se obtuvo
las preferencias del usuario del tiempo con el método is24HourFormat() de la clase DateFormat.

El paso a seguir es implementar la interfaz OnTimeSetListener en tu actividad principal para sobrescribir las
acciones del método de acción onTimeSet().

@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Toast.makeText(
this,
"Tiempo: " + hourOfDay + ":" + minute,
Toast.LENGTH_LONG)
.show();
}

Diálogos En Pantalla Completa O Full Screen


El uso de diálogos en pantalla completa se puede dar cuando el diálogo contiene varios elementos agrupados
que requieren más espacio. O en los procesos de inserción o edición de datos siempre y cuando no se requiera
guardar los datos en tiempo real.

También pueden usarse en situaciones donde el tamaño de la pantalla influye. Es decir, para tamaños pequeños
podría mostrarse el diálogo en pantalla completa y para tamaños grandes se desplegaría normalmente.

Lo curioso es que al crear un diálogo en pantalla completa, no podemos usar la clase AlertDialog junto a
Builder, debido a que el DialogFragment será embebido a través de una transacción de fragmentos como se
hace normalmente.

Esto significa que el método onCreateDialog() no será sobrescrito, por lo que debemos acudir a
onCreateView() para inflar un layout por completo.

Así que puedes deducir que las áreas de título, contenido y acción no están distribuida de la misma forma. Esta
vez los botones de confirmación y el título van en la action bar; y el contenido será ubicado en todo el espacio de
trabajo.

El siguiente ejemplo extraído de la guía de Material Design para diseño de diálogos full screen , muestra cómo se
vería este elemento:
Si lees un poco, nos indican que debemos ubicar la acción de
confirmación como action button con un verbo descriptivo
como “Guardar”, “Crear”, “Enviar”, etc. En caso de la acción
negativa, se usa el ícono de cerrar como Up Button.

Ejemplo de un fragmento full screen

Supón que deseas añadir una nueva cita de ventas a tu


aplicación gestora de vendedores y has decidido usar un
fragmento en pantalla completa para ello.

Sabes que necesitas el nombre del lead, el producto en que


está interesado, la fecha en que se acordó la reunión, la
prioridad y una sección para describir alguna situación
especial.

Para ello creas el siguiente layout:

fullscreen_dialog.xml

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

<ScrollView

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

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/activity_horizontal_margin">

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:paddingTop="@dimen/edit_text_padding"
android:text="@string/cliente_label"
android:textAppearance="?android:attr/textAppearanceSmall" />

<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentStart="true"

android:layout_below="@+id/textView"

android:entries="@array/clientes" />

<TextView
android:id="@+id/textView2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentStart="true"

android:layout_below="@+id/spinner"

android:paddingTop="@dimen/edit_text_padding"
android:text="@string/producto_label"
android:textAppearance="?android:attr/textAppearanceSmall" />

<Spinner
android:id="@+id/spinner2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/textView2"
android:entries="@array/productos" />

<TextView
android:id="@+id/fecha_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/spinner2"
android:paddingTop="@dimen/edit_text_padding"
android:text="@string/fecha_label"
android:textAppearance="?android:attr/textAppearanceSmall" />
<View
android:id="@+id/centro"
android:layout_width="1dp"
android:layout_height="1dp"
android:layout_centerInParent="true"
android:background="@null" />

<TextView
android:id="@+id/prioridad_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/fecha_text"
android:paddingTop="@dimen/edit_text_padding"
android:text="@string/prioridad_label"
android:textAppearance="?android:attr/textAppearanceSmall" />

<Spinner
android:id="@+id/spinner5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/prioridad_text"
android:entries="@array/prioridades" />

<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/spinner5"
android:paddingTop="@dimen/edit_text_padding"
android:text="@string/notas_label"
android:textAppearance="?android:attr/textAppearanceSmall" />

<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/textView5"
android:hint="@string/notas_hint"
android:textAppearance="?android:attr/textAppearanceSmall" />

<TextView
android:id="@+id/fecha_text"
style="@android:style/Widget.DeviceDefault.Light.Spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/fecha_label"
android:layout_marginRight="@dimen/normal_padding"
android:layout_toLeftOf="@+id/hora_text"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />

<TextView
android:id="@+id/hora_text"
style="@android:style/Widget.DeviceDefault.Light.Spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/fecha_label"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />

</RelativeLayout>
</ScrollView>

Para proseguir con ese diseño, simplemente debes crear un nuevo fragmento que extienda de DialogFragment
y sobrescribes el método onCreateView() para inflarlo.

FullScreenDialog.java

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.herprogramacion.dialogpers.R;

import java.text.SimpleDateFormat;
import java.util.Calendar;

public class FullScreenDialog extends DialogFragment {

private TextView textFecha;


private TextView textTiempo;
public FullScreenDialog() {
// Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
// Obtener instancia de la action bar
ActionBar actionBar = ((AppCompatActivity) getActivity())
.getSupportActionBar();

if (actionBar != null) {
// Habilitar el Up Button
actionBar.setDisplayHomeAsUpEnabled(true);
// Cambiar icono del Up Button
actionBar.setHomeAsUpIndicator(R.mipmap.ic_close);
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fullscreen_dialog, container, false);
iniciarHora(view);// Setear hora inicial
iniciarFecha(view);// Setear fecha inicial
return view;
}

private void iniciarHora(View view) {


textTiempo = (TextView) view.findViewById(R.id.hora_text);
Calendar c = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("HH:mm a");
textTiempo.setText(format.format(c.getTime()));

textTiempo.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
new TimeDialog().show(getFragmentManager(),
"TimePickerInFull");
}
}
);
}

private void iniciarFecha(View view) {


textFecha = (TextView) view.findViewById(R.id.fecha_text);
Calendar c = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("E MMM d yyyy");
textFecha.setText(format.format(c.getTime()));

textFecha.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
new DateDialog().show(getFragmentManager(),
"DatePickerInFull");
}
}
);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fullscreen_dialog, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();

switch (id) {
case android.R.id.home:
// procesarDescartar()
break;
case R.id.action_save:
// procesarGuardar()
break;
}

return super.onOptionsItemSelected(item);
}

/**
* Actualiza la fecha del view {@code fecha_text}
* @param year Nuevo Año
* @param monthOfYear Nuevo Mes
* @param dayOfMonth Nuevo día
*/
public void setDateView(int year, int monthOfYear, int dayOfMonth) {
Calendar c = Calendar.getInstance();
c.set(year, monthOfYear, dayOfMonth);
SimpleDateFormat format = new SimpleDateFormat("E MMM d yyyy");
textFecha.setText(format.format(c.getTime()));
}

/**
* Actualiza la hora del view {@code hora_text}
* @param hourOfDay Nueva Hora
* @param minute Nuevos Minutos
*/
public void setTimeView(int hourOfDay, int minute) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR, hourOfDay);
c.set(Calendar.MINUTE, minute);
SimpleDateFormat format = new SimpleDateFormat("HH:mm a");
textTiempo.setText(format.format(c.getTime()));
}
}

El estilo de la fecha y el tiempo puedes modificarlo a través de la clase SimpleDateFormat, la cual provee el
método format() para transformar información con respecto a un patrón.

Otra aspecto importante es la creación de un DateDialog y un TimeDialog al momento de pulsar los text
views de fecha y tiempo. Lo que quiere decir que se espera que la actividad implemente las escuchas para la
transferencia de los datos.

Ahora debes insertarlo en la actividad donde te encuentras. Lo que requiere una transacción simple de
fragmentos.

DetailActivity.java

import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.widget.DatePicker;
import android.widget.TimePicker;

import com.herprogramacion.dialogpers.R;
import com.herprogramacion.dialogpers.dialogos.FullScreenDialog;

public class DetailActivity extends AppCompatActivity implements


DatePickerDialog.OnDateSetListener,
TimePickerDialog.OnTimeSetListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
if (savedInstanceState == null) {
crearFullScreenDialog();
}
}

private void crearFullScreenDialog() {


FragmentManager fragmentManager = getSupportFragmentManager();
FullScreenDialog newFragment = new FullScreenDialog();

FragmentTransaction transaction = fragmentManager.beginTransaction();


transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.add(android.R.id.content, newFragment, "FullScreenFragment")
.commit();
}

@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int
dayOfMonth) {

FullScreenDialog fragment = (FullScreenDialog)


getSupportFragmentManager().findFragmentByTag("FullScreenFragment");
if (fragment != null) {
fragment.setDateView(year, monthOfYear, dayOfMonth);
}
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
FullScreenDialog fragment = (FullScreenDialog)
getSupportFragmentManager().findFragmentByTag("FullScreenFragment");
if (fragment != null) {
fragment.setTimeView(hourOfDay, minute);
}
}
}

Los métodos onDateSet() y onTimeSet() de las interfaces de los pickers acceden directamente al dialogo
FullScreenDialog para comunicar los datos. Si observaste bien, setDateView() y setTimeView() son los
métodos encargados de recibir los datos de las interfaces de comunicación.

Por último programamos las acciones de la action bar. Crea un nuevo menú llamado fullscreen_dialog.xml y
asígnale un action button para guardar:

fullscreen_dialog.xml

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


<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_save" android:title="@string/action_save"
android:orderInCategory="1" app:showAsAction="ifRoom" />
</menu>

Si analizas el fragmento FullScreenFragment, este contribuye a la action bar con onHasOptionsMenu()


dentro de onCreate(). Por esa razón se infla el menú en onCreateOptionsMenu().

El ícono de cerrar se implementó al obtener la action bar en onCreateView() para cambiar el icono del up
button con el método setHomeAsUpIndicator(). El drawable puedes encontrarlo al descargar el proyecto.

Recuerda que si necesitas implementar acciones de confirmación y descarte, tienes el método


onOptionsItemSelected(). Donde android.R.id.home permite para tomar el evento del up button.

Manejar Eventos De Descarte Y Cancelación De Un Diálogo


Afortunadamente los fragmentos son descartados en el momento que sus botones de acción son presionados o
incluso si el usuario presiona por fuera de su contenido. Pero en ocasiones muy extremas tal vez requieras cerrar
el diálogo manualmente.

Y esto es tan sencillo como usar el método dismiss() dentro de DialogFragment. Adicionalmente puedes
realizar acciones en ese instante con el método onDismiss().

// Dentro de un DialogFragment...
@Override
public void onDismiss(DialogInterface dialog) {
// Tus acciones
}

Por otro lado el diálogo puede ser cancelado sin aplicar los cambios a través de cancel(). Para procesar su
comportamiento puedes usar onCancel(), el cual es invocado si el usuario presiona el Back Button, si es
presionado el botón negativo o si se presiona por fuera del diálogo.

// Dentro de un DialogFragment...
@Override
public void onCancel(DialogInterface dialog) {
// Tus acciones
}

Conclusiones
Asegúrate de usar diálogos cuando desees que el usuario decida ante una situación de confirmación o
cuando sea necesario el ingreso de datos necesarios para el procesamiento de una acción.
La clase DialogFragment permite la relación de los diálogos con los eventos de un fragmento. Esto
reduce la complejidad de interacciones con la actividad.
Asegúrate de seguir los patrones de diseño y las medidas establecidas por Google para mantener una
excelente experiencia de usuario en tu aplicación.
Es importante mantener el diseño de tus diálogos personalizados adaptable a diferentes tipos de pantallas
y orientaciones. Esto maximizará la experiencia de usuario en tu app.

Icono de la aplicación

Вам также может понравиться