Cómo mostrar diálogos con DialogFragment

Un DialogFragment es una subclase de fragmento especial diseñada para crear y alojar diálogos. Aunque no necesitas alojar tu diálogo dentro de un fragmento, si lo haces, permites que el FragmentManager administre el estado del diálogo y lo restablezca automáticamente cuando se produzca un cambio de configuración.

Cómo crear un DialogFragment

Para crear un DialogFragment, crea una clase que extienda DialogFragment y anula onCreateDialog(), como se muestra en el siguiente ejemplo.

Kotlin

class PurchaseConfirmationDialogFragment : DialogFragment() {
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
            AlertDialog.Builder(requireContext())
                .setMessage(getString(R.string.order_confirmation))
                .setPositiveButton(getString(R.string.ok)) { _,_ -> }
                .create()

    companion object {
        const val TAG = "PurchaseConfirmationDialog"
    }
}

Java

public class PurchaseConfirmationDialogFragment extends DialogFragment {
   @NonNull
   @Override
   public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
       return new AlertDialog.Builder(requireContext())
               .setMessage(getString(R.string.order_confirmation))
               .setPositiveButton(getString(R.string.ok), (dialog, which) -> {} )
               .create();
   }

   public static String TAG = "PurchaseConfirmationDialog";
}

Así como onCreateView() crea una View raíz en un fragmento común, onCreateDialog() crea un Dialog para que se muestre como parte del DialogFragment. El DialogFragment gestiona la visualización de Dialog en los estados adecuados del ciclo de vida del fragmento.

Al igual que con onCreateView(), puedes mostrar cualquier subclase Dialog, por medio de onCreateDialog() y no estás limitado a usar AlertDialog.

Cómo mostrar el DialogFragment

No tienes que crear un elemento FragmentTransaction manualmente para mostrar tu DialogFragment. En su lugar, usa el método show() para mostrar tu diálogo. Puedes pasar una referencia a un FragmentManager y una String a los efectos de usarla como una etiqueta de FragmentTransaction.

Cuando crees un DialogFragment desde un Fragment, debes usar el FragmentManager secundario para que se restablezca correctamente el estado después de los cambios de configuración. Una etiqueta no nula te permite usar findFragmentByTag() para recuperar el DialogFragment más adelante.

Kotlin

// From another Fragment or Activity where you wish to show this
// PurchaseConfirmationDialogFragment.
PurchaseConfirmationDialogFragment().show(
     childFragmentManager, PurchaseConfirmationDialog.TAG)

Java

// From another Fragment or Activity where you wish to show this
// PurchaseConfirmationDialogFragment.
new PurchaseConfirmationDialogFragment().show(
       getChildFragmentManager(), PurchaseConfirmationDialog.TAG);

Para obtener un mayor control sobre FragmentTransaction, puedes usar la sobrecarga show() que acepta una FragmentTransaction existente.

Ciclo de vida de DialogFragment

Un DialogFragment sigue el ciclo de vida del fragmento estándar, con algunas devoluciones de llamada relacionadas adicionales. Las más comunes son las siguientes:

  • onCreateDialog(): Anula esta devolución de llamada para proporcionar un Dialog para que el fragmento lo administre y lo muestre.
  • onDismiss(): Anula esta devolución de llamada si necesitas realizar cualquier lógica personalizada cuando se cancele tu Dialog, como liberar recursos o anular la suscripción a recursos observables.
  • onCancel(): Anula esta devolución de llamada si necesitas realizar cualquier lógica personalizada cuando se cancele tu Dialog.

DialogFragment también contiene métodos para descartar o establecer la capacidad de cancelación de tu DialogFragment:

  • dismiss(): Ignora el fragmento y su diálogo. Si el fragmento se agregó a la pila de actividades, aparecerán todos los estados de la pila de actividades hasta esta entrada inclusive. De lo contrario, una nueva transacción confirmará la eliminación del fragmento.
  • setCancelable(): Controla si se puede cancelar el Dialog mostrado. Usa este método en lugar de llamar directamente a Dialog.setCancelable(boolean).

No se anulan onCreateView() ni onViewCreated() cuando se usa un DialogFragment con un Dialog. Los diálogos no son solo vistas, sino que tienen su propia ventana. Por lo tanto, no es suficiente para anular onCreateView(). Además, nunca se llama a onViewCreated() en un DialogFragment personalizado, a menos que hayas anulado onCreateView() y proporcionado una vista no nula.

Cómo usar vistas personalizadas

Puedes crear un DialogFragment y mostrar un diálogo anulando onCreateView(). Puedes asignarle un layoutId, como en el caso de un fragmento típico, o bien usar el constructor DialogFragment.

La View que muestra onCreateView()se agrega automáticamente al diálogo. En la mayoría de los casos, esto significa que no necesitas anular onCreateDialog(), ya que el diálogo vacío predeterminado se propaga con tu vista.

Algunas subclases de DialogFragment, como BottomSheetDialogFragment, incorporan tu vista en un diálogo al que se le aplica el estilo de una hoja inferior.