Diálogos

Prueba el estilo de Compose
Jetpack Compose es el kit de herramientas de IU recomendado para Android. Aprende a agregar componentes en Compose.

Un diálogo es una ventana pequeña que le solicita al usuario que tome una decisión o ingrese información adicional. Un diálogo no ocupa toda la pantalla y, por lo general, se usa para eventos modales que requieren que los usuarios realicen una acción para poder continuar.

Imagen que muestra un diálogo básico
Figura 1: Un diálogo básico.

La clase Dialog es la clase base para los diálogos, pero no crees instancias de Dialog directamente. En su lugar, usa una de las siguientes subclases:

AlertDialog
Un diálogo que puede mostrar un título, hasta tres botones, una lista de elementos seleccionables o un diseño personalizado.
DatePickerDialog o TimePickerDialog
Es un diálogo con una IU predefinida que permite al usuario seleccionar una hora o fecha.

Estas clases definen el estilo y la estructura de tu diálogo. También necesitas un DialogFragment como contenedor para tu diálogo. La clase DialogFragment proporciona todos los controles que necesitas para crear tu diálogo y administrar su apariencia, en lugar de llamar a los métodos en el objeto Dialog.

El uso de DialogFragment para administrar el diálogo permite controlar correctamente los eventos de ciclo de vida, como cuando el usuario presiona el botón Atrás o rota la pantalla. La clase DialogFragment también te permite reutilizar la IU del diálogo como un componente integrable en una IU más grande, al igual que un Fragment tradicional, como cuando quieres que la IU del diálogo se muestre de manera diferente en pantallas grandes y pequeñas.

En las siguientes secciones de este documento, se describe cómo usar un DialogFragment junto con un objeto AlertDialog. Si deseas crear un selector de fecha y hora, consulta Cómo agregar selectores a tu app.

Cómo crear un fragmento de diálogo

Puedes lograr una amplia variedad de diseños de diálogo, incluidos diseños personalizados y los que se describen en Diálogos de Material Design, si extiendes DialogFragment y creas un AlertDialog en el método de devolución de llamada onCreateDialog().

Por ejemplo, aquí hay un AlertDialog básico administrado dentro de un DialogFragment:

Kotlin

class StartGameDialogFragment : DialogFragment() {
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            // Use the Builder class for convenient dialog construction.
            val builder = AlertDialog.Builder(it)
            builder.setMessage("Start game")
                .setPositiveButton("Start") { dialog, id ->
                    // START THE GAME!
                }
                .setNegativeButton("Cancel") { dialog, id ->
                    // User cancelled the dialog.
                }
            // Create the AlertDialog object and return it.
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }
}

class OldXmlActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_old_xml)

        StartGameDialogFragment().show(supportFragmentManager, "GAME_DIALOG")
    }
}

Java

public class StartGameDialogFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction.
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_start_game)
               .setPositiveButton(R.string.start, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // START THE GAME!
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // User cancels the dialog.
                   }
               });
        // Create the AlertDialog object and return it.
        return builder.create();
    }
}
// ...

StartGameDialogFragment().show(supportFragmentManager, "GAME_DIALOG");

Cuando creas una instancia de esta clase y llamas a show() en ese objeto, el diálogo aparece como se muestra en la siguiente figura.

Una imagen que muestra un diálogo básico con dos botones de acción
Figura 2: Un diálogo con un mensaje y dos botones de acción.

En la siguiente sección, se proporcionan más detalles sobre el uso de las APIs de AlertDialog.Builder para crear el diálogo.

Según la complejidad del diálogo, puedes implementar una variedad de otros métodos de devolución de llamada en DialogFragment, incluidos todos los métodos básicos del ciclo de vida del fragmento.

Crea un diálogo de alerta

La clase AlertDialog te permite compilar una variedad de diseños de diálogo y, a menudo, es la única clase de diálogo que necesitas. Como se muestra en la siguiente figura, hay tres regiones en un diálogo de alerta:

  • Título: es opcional y solo se usa cuando el área de contenido está ocupada por un mensaje detallado, una lista o un diseño personalizado. Si necesitas indicar un mensaje o una pregunta simple, no necesitas un título.
  • Área de contenido: Puede mostrar un mensaje, una lista o cualquier otro diseño personalizado.
  • Botones de acción: Puede haber hasta tres botones de acción en un diálogo.

La clase AlertDialog.Builder proporciona APIs que te permiten crear un AlertDialog con estos tipos de contenido, incluido un diseño personalizado.

Para compilar un AlertDialog, haz lo siguiente:

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setMessage("I am the message")
    .setTitle("I am the title")

val dialog: AlertDialog = builder.create()
dialog.show()

Java

// 1. Instantiate an AlertDialog.Builder with its constructor.
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

// 2. Chain together various setter methods to set the dialog characteristics.
builder.setMessage(R.string.dialog_message)
       .setTitle(R.string.dialog_title);

// 3. Get the AlertDialog.
AlertDialog dialog = builder.create();

El fragmento de código anterior genera el siguiente diálogo:

Una imagen que muestra un diálogo con título, área de contenido y dos botones de acción.
Figura 3: El diseño de un diálogo de alerta básico.

Cómo agregar botones

Para agregar botones de acción como los de la Figura 2, llama a los métodos setPositiveButton() y setNegativeButton():

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setMessage("I am the message")
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

Java

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Add the buttons.
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User taps OK button.
           }
       });
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // User cancels the dialog.
           }
       });
// Set other dialog properties.
...

// Create the AlertDialog.
AlertDialog dialog = builder.create();

Los métodos set...Button() requieren un título para el botón (proporcionado por un recurso de cadenas) y un DialogInterface.OnClickListener que defina la acción que se realizará cuando el usuario presione el botón.

Existen tres botones de acción que puedes agregar:

  • Positivo: Usa este botón para aceptar y continuar con la acción (la acción "OK").
  • Negativa: Usa esta opción para cancelar la acción.
  • Neutral: Úsalo cuando el usuario no quiera continuar con la acción, pero no necesariamente quiera cancelarla. Aparece entre los botones positivo y negativo. Por ejemplo, la acción podría ser "Recordarme más tarde".

Puedes agregar un solo tipo de botón a un AlertDialog. Por ejemplo, no puedes tener más de un botón “positivo”.

El fragmento de código anterior te proporciona un diálogo de alerta como el siguiente:

Una imagen que muestra un diálogo de alerta con título, mensaje y dos botones de acción.
Figura 4: Un diálogo de alerta con título, mensaje y dos botones de acción.

Agregar una lista

Hay tres tipos de listas disponibles con las APIs de AlertDialog:

  • Una lista tradicional de opción única.
  • Una lista de opción única persistente (botones de selección)
  • Una lista de opción múltiple persistente (casillas de verificación)

Para crear una lista de opción única como la de la Figura 5, usa el método setItems():


Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setItems(arrayOf("Item One", "Item Two", "Item Three")) { dialog, which ->
        // Do something on item tapped.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

Java

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle(R.string.pick_color)
           .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int which) {
               // The 'which' argument contains the index position of the selected item.
           }
    });
    return builder.create();
}

Este fragmento de código genera un diálogo como el siguiente:

Una imagen que muestra un diálogo con un título y una lista.
Figura 5: Un diálogo con un título y una lista

Como la lista aparece en el área de contenido del diálogo, este no puede mostrar un mensaje y una lista al mismo tiempo. Establece un título para el diálogo con setTitle(). Para especificar los elementos de la lista, llama a setItems() pasando un array. Como alternativa, puedes especificar una lista con setAdapter(). Esto te permite respaldar la lista con datos dinámicos, como los de una base de datos, mediante un ListAdapter.

Si respaldas tu lista con un ListAdapter, siempre usa un Loader para que el contenido se cargue de forma asíncrona. Esto se describe más detalladamente en Cómo compilar diseños con un adaptador y en Cargadores.

Cómo agregar una lista persistente de opción única o múltiple

Para agregar una lista de elementos de opción múltiple (casillas de verificación) o de opción única (botones de selección), usa los métodos setMultiChoiceItems() o setSingleChoiceItems(), respectivamente.

Por ejemplo, aquí te mostramos cómo puedes crear una lista de opción múltiple como la que se muestra en la figura 6, que guarda los elementos seleccionados en un ArrayList:

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setMultiChoiceItems(
        arrayOf("Item One", "Item Two", "Item Three"), null) { dialog, which, isChecked ->
        // Do something.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

Java

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    selectedItems = new ArrayList();  // Where we track the selected items
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Set the dialog title.
    builder.setTitle(R.string.pick_toppings)
    // Specify the list array, the items to be selected by default (null for
    // none), and the listener through which to receive callbacks when items
    // are selected.
           .setMultiChoiceItems(R.array.toppings, null,
                      new DialogInterface.OnMultiChoiceClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int which,
                       boolean isChecked) {
                   if (isChecked) {
                       // If the user checks the item, add it to the selected
                       // items.
                       selectedItems.add(which);
                   } else if (selectedItems.contains(which)) {
                       // If the item is already in the array, remove it.
                       selectedItems.remove(which);
                   }
               }
           })
    // Set the action buttons
           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // User taps OK, so save the selectedItems results
                   // somewhere or return them to the component that opens the
                   // dialog.
                   ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   ...
               }
           });

    return builder.create();
}
Una imagen que muestra un diálogo con una lista con elementos de opción múltiple.
Figura 6: Una lista con elementos de opción múltiple.

Se puede obtener un diálogo de alerta de opción única de la siguiente manera:

Kotlin

val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
    .setTitle("I am the title")
    .setPositiveButton("Positive") { dialog, which ->
        // Do something.
    }
    .setNegativeButton("Negative") { dialog, which ->
        // Do something else.
    }
    .setSingleChoiceItems(
        arrayOf("Item One", "Item Two", "Item Three"), 0
    ) { dialog, which ->
        // Do something.
    }

val dialog: AlertDialog = builder.create()
dialog.show()

Java

        String[] choices = {"Item One", "Item Two", "Item Three"};
        
        AlertDialog.Builder builder = AlertDialog.Builder(context);
        builder
                .setTitle("I am the title")
                .setPositiveButton("Positive", (dialog, which) -> {

                })
                .setNegativeButton("Negative", (dialog, which) -> {

                })
                .setSingleChoiceItems(choices, 0, (dialog, which) -> {

                });

        AlertDialog dialog = builder.create();
        dialog.show();

Esto da como resultado el siguiente ejemplo:

Una imagen que muestra un diálogo que contiene una lista de elementos de opción única.
Figura 7: Una lista de elementos de opción única.

Cómo crear un diseño personalizado

Si quieres un diseño personalizado en un diálogo, crea un diseño y agrégalo a un AlertDialog llamando a setView() en tu objeto AlertDialog.Builder.

Una imagen que muestra un diseño de diálogo personalizado.
Figura 8: Un diseño de diálogo personalizado

De forma predeterminada, el diseño personalizado ocupa toda la ventana de diálogo, pero aún puedes usar métodos AlertDialog.Builder para agregar botones y un título.

Por ejemplo, este es el archivo de diseño para el diseño de diálogo personalizado anterior:

res/layout/dialog_signin.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <ImageView
        android:src="@drawable/header_logo"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:scaleType="center"
        android:background="#FFFFBB33"
        android:contentDescription="@string/app_name" />
    <EditText
        android:id="@+id/username"
        android:inputType="textEmailAddress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="4dp"
        android:hint="@string/username" />
    <EditText
        android:id="@+id/password"
        android:inputType="textPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginBottom="16dp"
        android:fontFamily="sans-serif"
        android:hint="@string/password"/>
</LinearLayout>

Para aumentar el diseño en tu DialogFragment, obtén un LayoutInflater con getLayoutInflater() y llama a inflate(). El primer parámetro es el ID del recurso de diseño y el segundo es una vista superior del diseño. Luego, puedes llamar a setView() para colocar el diseño en el diálogo. Esto se muestra en el siguiente ejemplo.

Kotlin

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return activity?.let {
        val builder = AlertDialog.Builder(it)
        // Get the layout inflater.
        val inflater = requireActivity().layoutInflater;

        // Inflate and set the layout for the dialog.
        // Pass null as the parent view because it's going in the dialog
        // layout.
        builder.setView(inflater.inflate(R.layout.dialog_signin, null))
                // Add action buttons.
                .setPositiveButton(R.string.signin,
                        DialogInterface.OnClickListener { dialog, id ->
                            // Sign in the user.
                        })
                .setNegativeButton(R.string.cancel,
                        DialogInterface.OnClickListener { dialog, id ->
                            getDialog().cancel()
                        })
        builder.create()
    } ?: throw IllegalStateException("Activity cannot be null")
}

Java

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Get the layout inflater.
    LayoutInflater inflater = requireActivity().getLayoutInflater();

    // Inflate and set the layout for the dialog.
    // Pass null as the parent view because it's going in the dialog layout.
    builder.setView(inflater.inflate(R.layout.dialog_signin, null))
    // Add action buttons
           .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // Sign in the user.
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   LoginDialogFragment.this.getDialog().cancel();
               }
           });
    return builder.create();
}

Si quieres un diálogo personalizado, puedes mostrar una Activity como diálogo en lugar de usar las APIs de Dialog. Crea una actividad y establece su tema como Theme.Holo.Dialog en el elemento de manifiesto <activity>:

<activity android:theme="@android:style/Theme.Holo.Dialog" >

Ahora la actividad se muestra en una ventana de diálogo en lugar de mostrarse en pantalla completa.

Pasa eventos de vuelta al host del diálogo

Cuando el usuario presiona uno de los botones de acción del diálogo o selecciona un elemento de su lista, tu DialogFragment podría realizar la acción necesaria por su cuenta, pero a menudo quieres enviar el evento a la actividad o al fragmento que abre el diálogo. Para ello, define una interfaz con un método para cada tipo de evento de clic. Luego, implementa esa interfaz en el componente de host que recibe los eventos de acción del diálogo.

Por ejemplo, este es un DialogFragment que define una interfaz a través de la cual envía eventos de vuelta a la actividad del host:

Kotlin

class NoticeDialogFragment : DialogFragment() {
    // Use this instance of the interface to deliver action events.
    internal lateinit var listener: NoticeDialogListener

    // The activity that creates an instance of this dialog fragment must
    // implement this interface to receive event callbacks. Each method passes
    // the DialogFragment in case the host needs to query it.
    interface NoticeDialogListener {
        fun onDialogPositiveClick(dialog: DialogFragment)
        fun onDialogNegativeClick(dialog: DialogFragment)
    }

    // Override the Fragment.onAttach() method to instantiate the
    // NoticeDialogListener.
    override fun onAttach(context: Context) {
        super.onAttach(context)
        // Verify that the host activity implements the callback interface.
        try {
            // Instantiate the NoticeDialogListener so you can send events to
            // the host.
            listener = context as NoticeDialogListener
        } catch (e: ClassCastException) {
            // The activity doesn't implement the interface. Throw exception.
            throw ClassCastException((context.toString() +
                    " must implement NoticeDialogListener"))
        }
    }
}

Java

public class NoticeDialogFragment extends DialogFragment {

    // The activity that creates an instance of this dialog fragment must
    // implement this interface to receive event callbacks. Each method passes
    // the DialogFragment in case the host needs to query it.
    public interface NoticeDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
    }

    // Use this instance of the interface to deliver action events.
    NoticeDialogListener listener;

    // Override the Fragment.onAttach() method to instantiate the
    // NoticeDialogListener.
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // Verify that the host activity implements the callback interface.
        try {
            // Instantiate the NoticeDialogListener so you can send events to
            // the host.
            listener = (NoticeDialogListener) context;
        } catch (ClassCastException e) {
            // The activity doesn't implement the interface. Throw exception.
            throw new ClassCastException(activity.toString()
                    + " must implement NoticeDialogListener");
        }
    }
    ...
}

La actividad que aloja el diálogo crea una instancia del diálogo con el constructor del fragmento y recibe los eventos del diálogo a través de una implementación de la interfaz NoticeDialogListener:

Kotlin

class MainActivity : FragmentActivity(),
        NoticeDialogFragment.NoticeDialogListener {

    fun showNoticeDialog() {
        // Create an instance of the dialog fragment and show it.
        val dialog = NoticeDialogFragment()
        dialog.show(supportFragmentManager, "NoticeDialogFragment")
    }

    // The dialog fragment receives a reference to this Activity through the
    // Fragment.onAttach() callback, which it uses to call the following
    // methods defined by the NoticeDialogFragment.NoticeDialogListener
    // interface.
    override fun onDialogPositiveClick(dialog: DialogFragment) {
        // User taps the dialog's positive button.
    }

    override fun onDialogNegativeClick(dialog: DialogFragment) {
        // User taps the dialog's negative button.
    }
}

Java

public class MainActivity extends FragmentActivity
                          implements NoticeDialogFragment.NoticeDialogListener{
    ...
    public void showNoticeDialog() {
        // Create an instance of the dialog fragment and show it.
        DialogFragment dialog = new NoticeDialogFragment();
        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
    }

    // The dialog fragment receives a reference to this Activity through the
    // Fragment.onAttach() callback, which it uses to call the following
    // methods defined by the NoticeDialogFragment.NoticeDialogListener
    // interface.
    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        // User taps the dialog's positive button.
        ...
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        // User taps the dialog's negative button.
        ...
    }
}

Debido a que la actividad de host implementa NoticeDialogListener (que se aplica de manera forzosa por el método de devolución de llamada onAttach() que se muestra en el ejemplo anterior), el fragmento de diálogo puede usar los métodos de devolución de llamada de la interfaz para enviar eventos de clic a la actividad:

Kotlin

    override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
        return activity?.let {
            // Build the dialog and set up the button click handlers.
            val builder = AlertDialog.Builder(it)

            builder.setMessage(R.string.dialog_start_game)
                    .setPositiveButton(R.string.start,
                            DialogInterface.OnClickListener { dialog, id ->
                                // Send the positive button event back to the
                                // host activity.
                                listener.onDialogPositiveClick(this)
                            })
                    .setNegativeButton(R.string.cancel,
                            DialogInterface.OnClickListener { dialog, id ->
                                // Send the negative button event back to the
                                // host activity.
                                listener.onDialogNegativeClick(this)
                            })

            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }

Java

public class NoticeDialogFragment extends DialogFragment {
    ...
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Build the dialog and set up the button click handlers.
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_start_game)
               .setPositiveButton(R.string.start, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the positive button event back to the host activity.
                       listener.onDialogPositiveClick(NoticeDialogFragment.this);
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the negative button event back to the host activity.
                       listener.onDialogNegativeClick(NoticeDialogFragment.this);
                   }
               });
        return builder.create();
    }
}

Mostrar un diálogo

Cuando desees mostrar tu diálogo, crea una instancia de tu DialogFragment, llama a show() y pasa el FragmentManager y un nombre de etiqueta para el fragmento de diálogo.

Para obtener el FragmentManager, llama a getSupportFragmentManager() desde FragmentActivity o llama a getParentFragmentManager() desde un Fragment. Consulta los siguientes ejemplos:

Kotlin

fun confirmStartGame() {
    val newFragment = StartGameDialogFragment()
    newFragment.show(supportFragmentManager, "game")
}

Java

public void confirmStartGame() {
    DialogFragment newFragment = new StartGameDialogFragment();
    newFragment.show(getSupportFragmentManager(), "game");
}

El segundo argumento, "game", es un nombre de etiqueta único que el sistema usa para guardar y restablecer el estado del fragmento cuando es necesario. La etiqueta también te permite obtener un controlador para el fragmento llamando a findFragmentByTag().

Muestra un diálogo en pantalla completa o como un fragmento integrado

Tal vez quieras que una parte de tu diseño de la IU aparezca como un diálogo en algunas situaciones y como un fragmento de pantalla completa o incorporado en otras. También puedes querer que se vea de manera diferente según el tamaño de la pantalla del dispositivo. La clase DialogFragment ofrece flexibilidad para lograr esto, ya que puede comportarse como un Fragment integrable.

Sin embargo, en este caso no puedes usar AlertDialog.Builder ni otros objetos Dialog para compilar el diálogo. Si quieres que DialogFragment se pueda incorporar, define la IU del diálogo en un diseño y, luego, cárgalo en la devolución de llamada onCreateView().

Este es un DialogFragment de ejemplo que puede aparecer como un diálogo o un fragmento integrable, con un diseño llamado purchase_items.xml:

Kotlin

class CustomDialogFragment : DialogFragment() {

    // The system calls this to get the DialogFragment's layout, regardless of
    // whether it's being displayed as a dialog or an embedded fragment.
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        // Inflate the layout to use as a dialog or embedded fragment.
        return inflater.inflate(R.layout.purchase_items, container, false)
    }

    // The system calls this only when creating the layout in a dialog.
    override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
        // The only reason you might override this method when using
        // onCreateView() is to modify the dialog characteristics. For example,
        // the dialog includes a title by default, but your custom layout might
        // not need it. Here, you can remove the dialog title, but you must
        // call the superclass to get the Dialog.
        val dialog = super.onCreateDialog(savedInstanceState)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        return dialog
    }
}

Java

public class CustomDialogFragment extends DialogFragment {
    // The system calls this to get the DialogFragment's layout, regardless of
    // whether it's being displayed as a dialog or an embedded fragment.
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout to use as a dialog or embedded fragment.
        return inflater.inflate(R.layout.purchase_items, container, false);
    }

    // The system calls this only when creating the layout in a dialog.
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // The only reason you might override this method when using
        // onCreateView() is to modify the dialog characteristics. For example,
        // the dialog includes a title by default, but your custom layout might
        // not need it. Here, you can remove the dialog title, but you must
        // call the superclass to get the Dialog.
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        return dialog;
    }
}

En el siguiente ejemplo, se determina si se muestra el fragmento como un diálogo o una IU en pantalla completa en función del tamaño de la pantalla:

Kotlin

fun showDialog() {
    val fragmentManager = supportFragmentManager
    val newFragment = CustomDialogFragment()
    if (isLargeLayout) {
        // The device is using a large layout, so show the fragment as a
        // dialog.
        newFragment.show(fragmentManager, "dialog")
    } else {
        // The device is smaller, so show the fragment fullscreen.
        val transaction = fragmentManager.beginTransaction()
        // For a polished look, specify a transition animation.
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity.
        transaction
                .add(android.R.id.content, newFragment)
                .addToBackStack(null)
                .commit()
    }
}

Java

public void showDialog() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    CustomDialogFragment newFragment = new CustomDialogFragment();

    if (isLargeLayout) {
        // The device is using a large layout, so show the fragment as a
        // dialog.
        newFragment.show(fragmentManager, "dialog");
    } else {
        // The device is smaller, so show the fragment fullscreen.
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        // For a polished look, specify a transition animation.
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity.
        transaction.add(android.R.id.content, newFragment)
                   .addToBackStack(null).commit();
    }
}

Para obtener más información acerca de cómo realizar transacciones con fragmentos, consulta Fragmentos.

En este ejemplo, el booleano mIsLargeLayout especifica si el dispositivo actual debe usar el diseño grande de la app y, por lo tanto, mostrar este fragmento como un diálogo en lugar de pantalla completa. La mejor manera de establecer este tipo de valor booleano es declarar un valor de recurso booleano con un valor de recurso alternativo para diferentes tamaños de pantalla. Por ejemplo, a continuación se muestran dos versiones del recurso booleano para diferentes tamaños de pantalla:

res/values/bools.xml

<!-- Default boolean values -->
<resources>
    <bool name="large_layout">false</bool>
</resources>

res/values-large/bools.xml

<!-- Large screen boolean values -->
<resources>
    <bool name="large_layout">true</bool>
</resources>

Luego, puedes inicializar el valor mIsLargeLayout durante el método onCreate() de la actividad, como se muestra en el siguiente ejemplo:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    isLargeLayout = resources.getBoolean(R.bool.large_layout)
}

Java

boolean isLargeLayout;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    isLargeLayout = getResources().getBoolean(R.bool.large_layout);
}

Cómo mostrar una actividad como un diálogo en pantallas grandes

En lugar de mostrar un diálogo como una IU de pantalla completa en pantallas pequeñas, puedes obtener el mismo resultado mostrando un Activity como un diálogo en pantallas grandes. El enfoque que elijas depende del diseño de tu app, pero mostrar una actividad como un diálogo suele ser útil cuando tu app está diseñada para pantallas pequeñas y deseas mejorar la experiencia en tablets mostrando una actividad de corta duración como un diálogo.

Para mostrar una actividad como diálogo solo en pantallas grandes, aplica el tema Theme.Holo.DialogWhenLarge al elemento de manifiesto <activity>:

<activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" >

Si deseas obtener más información para diseñar tus actividades con temas, consulta Estilos y temas.

Cómo descartar un diálogo

Cuando el usuario presiona un botón de acción creado con un AlertDialog.Builder, el sistema descarta el diálogo por ti.

El sistema también descarta el diálogo cuando el usuario presiona un elemento en una lista de diálogo, excepto cuando la lista usa botones de selección o casillas de verificación. De lo contrario, puedes descartar el diálogo de forma manual llamando a dismiss() en tu DialogFragment.

Si necesitas realizar ciertas acciones cuando el diálogo desaparezca, puedes implementar el método onDismiss() en tu DialogFragment.

También puedes cancelar un diálogo. Este es un evento especial que indica que el usuario abandona el diálogo sin completar la tarea. Esto ocurre si el usuario presiona el botón Atrás o la pantalla fuera del área del diálogo, o bien si llamas explícitamente a cancel() en el Dialog, como en respuesta a un botón "Cancelar" en el diálogo.

Como se muestra en el ejemplo anterior, puedes responder al evento de cancelación mediante la implementación de onCancel() en tu clase DialogFragment.