Android DialogFragment vs Dialog


244

Google recomienda que usemos en DialogFragmentlugar de un simple Dialogmediante el uso Fragments API, pero es absurdo usar un DialogFragmentcuadro de mensaje de confirmación aislado para un simple Sí-No. ¿Cuál es la mejor práctica en este caso?


55
En resumen, entre otras cosas, simple Dialogo AlertDialog.Builder::create()::show()creará un cuadro de diálogo que desaparecerá cuando gire la pantalla.
user1032613

Respuestas:


83

Sí, use DialogFragmenty onCreateDialogpuede simplemente usar un generador de AlertDialog de todos modos para crear un simple AlertDialogcon los botones de confirmación Sí / No. No hay mucho código en absoluto.

Con respecto al manejo de eventos en su fragmento, habría varias formas de hacerlo, pero simplemente defino un mensaje Handleren mi Fragment, lo paso a DialogFragmenttravés de su constructor y luego paso los mensajes al controlador de mi fragmento según corresponda en los diversos eventos de clic. De nuevo varias formas de hacerlo, pero lo siguiente funciona para mí.

En el cuadro de diálogo, mantenga un mensaje y ejemplifíquelo en el constructor:

private Message okMessage;
...
okMessage = handler.obtainMessage(MY_MSG_WHAT, MY_MSG_OK);

Implemente el onClickListeneren su diálogo y luego llame al controlador según corresponda:

public void onClick(.....
    if (which == DialogInterface.BUTTON_POSITIVE) {
        final Message toSend = Message.obtain(okMessage);
        toSend.sendToTarget();
    }
 }

Editar

Y como Messagees parcelable, puede guardarlo onSaveInstanceStatey restaurarlo

outState.putParcelable("okMessage", okMessage);

Entonces en onCreate

if (savedInstanceState != null) {
    okMessage = savedInstanceState.getParcelable("okMessage");
}

44
El problema no es okMessage: el problema es okMessage, targetque será nulo si lo carga desde un paquete. Si el objetivo de un mensaje es nulo, y usted lo usa sendToTarget, obtendrá una excepción NullPointerException, no porque el mensaje sea nulo, sino porque su objetivo sí lo es.
hrnt

2
¿Cuáles son las ventajas de usar DialogFragment en lugar de Dialog?
Raphael Petegrosso

80
La ventaja de usar un DialogFragment es que todo el ciclo de vida del diálogo se manejará por usted. Nunca volverá a aparecer el error "se ha filtrado el diálogo ...". Vaya a DialogFragment y olvide Diálogos.
Snicolas

66
Creo que setArguments () y getArguments () deberían usarse en lugar de pasar el okMessage a través del constructor.
pjv

1
Bueno, utilizo Builder con bastante facilidad y manejo la gestión de actividades con este android: configChanges = "locale | keyboardHidden | orientación | screenSize" y no veo ningún problema en las aplicaciones ...
Renetik

67

Puede crear subclases genéricas de DialogFragment como YesNoDialog y OkDialog, y pasar el título y el mensaje si usa mucho los diálogos en su aplicación.

public class YesNoDialog extends DialogFragment
{
    public static final String ARG_TITLE = "YesNoDialog.Title";
    public static final String ARG_MESSAGE = "YesNoDialog.Message";

    public YesNoDialog()
    {

    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        Bundle args = getArguments();
        String title = args.getString(ARG_TITLE);
        String message = args.getString(ARG_MESSAGE);

        return new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                }
            })
            .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, null);
                }
            })
            .create();
    }
}

Luego llámalo usando lo siguiente:

    DialogFragment dialog = new YesNoDialog();
    Bundle args = new Bundle();
    args.putString(YesNoDialog.ARG_TITLE, title);
    args.putString(YesNoDialog.ARG_MESSAGE, message);
    dialog.setArguments(args);
    dialog.setTargetFragment(this, YES_NO_CALL);
    dialog.show(getFragmentManager(), "tag");

Y maneje el resultado adentro onActivityResult.


Sí, DialogFragment maneja todos los eventos del ciclo de vida por usted.
ashishduh

1
Creo que no porque después de la rotación, el antiguo cuadro de diálogo todavía existe y se mantiene asignado al antiguo fragmento no existente (dialog.setTargetFragment (this, YES_NO_CALL);) así que después de la rotación getTargetFragment (). OnActivityResult no funciona
Malachiasz

77
lo que son YES_NO_CALL, getFragmentManager()y onActivityResult?
msysmilu

2
YES_NO_CALLes un int personalizado que es el código de solicitud. getFragmentManager()obtiene el administrador de fragmentos para la actividad y onActivityResult()es un método de devolución de llamada de ciclo de vida de fragmentos.
ashishduh

3
Reemplace getFragmentManager () con getSupportFragmentManager ();
Avinash Verma

33

Use DialogFragment sobre AlertDialog:


  • Desde la introducción del nivel 13 de API :

    la showDialog método de la Actividad está en desuso . No es aconsejable invocar un cuadro de diálogo en otra parte del código, ya que tendrá que administrar el cuadro de diálogo usted mismo (por ejemplo, cambio de orientación).

  • DiálogoFragmento de diferencia - AlertDialog

    ¿Son muy diferentes? De la referencia de Android con respecto a DialogFragment :

    Un DialogFragment es un fragmento que muestra una ventana de diálogo, flotando en la parte superior de la ventana de su actividad. Este fragmento contiene un objeto de diálogo, que se muestra según corresponda según el estado del fragmento. El control del diálogo (decidir cuándo mostrarlo, ocultarlo, descartarlo) debe hacerse a través de la API aquí , no con llamadas directas en el diálogo.

  • Otras notas

    • Los fragmentos son una evolución natural en el marco de Android debido a la diversidad de dispositivos con diferentes tamaños de pantalla.
    • DialogFragments y Fragments están disponibles en la biblioteca de soporte que hace que la clase sea utilizable en todas las versiones actuales de Android.

28

Yo recomendaría usar DialogFragment.

Claro, crear un cuadro de diálogo "Sí / No" con él es bastante complejo teniendo en cuenta que debería ser una tarea bastante simple, pero crear un cuadro de diálogo similar también Dialoges sorprendentemente complicado.

(El ciclo de vida de la actividad lo hace complicado, debe permitir Activityadministrar el ciclo de vida del cuadro de diálogo, y no hay forma de pasar parámetros personalizados, por ejemplo, el mensaje personalizado Activity.showDialogsi se usan niveles API inferiores a 8)

Lo bueno es que generalmente puedes construir tu propia abstracción además de DialogFragmentbastante fácilmente.


¿Cómo manejará las devoluciones de llamada del diálogo de alerta (sí, no)?
Alexey Zakharov

La forma más fácil sería implementar un método en la Actividad de alojamiento que tome un Stringparámetro. Cuando el usuario hace clic en "Sí", por ejemplo, el cuadro de diálogo llama al método de la Actividad con el parámetro "aceptar". Estos parámetros se especifican al mostrar el diálogo, por ejemplo AskDialog.ask ("¿Está de acuerdo con estos términos?", "De acuerdo", "en desacuerdo");
hrnt

55
Pero necesito devolución de llamada dentro del fragmento, no actividad. Puedo usar setTargetFragment y enviarlo a la interfaz. Pero es el infierno.
Alexey Zakharov

También puede obtener el fragmento de destino estableciendo una etiqueta en el objetivo y utilizando FragmentManager's findFragmentByTag. Pero sí, requiere un poco de código.
hrnt

@AlexeyZakharov Sé que esto es alrededor de 5 años de retraso, pero podría pasar Fragment this y tener Activity extendssu Interface. Sin embargo, con cuidado de enhebrar, podría estar saltando las llamadas de la interfaz cuando no necesariamente las quiere si su concurrencia no está bajo control. Sin embargo, no estoy seguro de lo que esto hace con la memoria y los espaguetis de dependencia circular, ¿a alguien más le gustaría intervenir? La otra opción es Message/ Handlerpero aún puede tener problemas de concurrencia.
tricknology

8

Generic AlertDialogFragment with Builder Pattern

En mi proyecto, que ya se utiliza AlertDialog.Builderya mucho antes de descubrir que es problemático. Sin embargo, no quería cambiar tanto código en ninguna parte de mi aplicación. Además, en realidad soy fanático de pasar OnClickListenerscomo clases anónimas donde se necesitan (es decir, cuando se usa setPositiveButton(), setNegativeButton()etc.) en lugar de tener que implementar miles de métodos de devolución de llamada para comunicarse entre un fragmento de diálogo y el fragmento del titular, que puede, en mi opinión, lleva a un código muy confuso y complejo. Especialmente, si tiene múltiples diálogos diferentes en un fragmento y luego necesita distinguir en las implementaciones de devolución de llamada entre qué diálogo se muestra actualmente.

Por lo tanto, combiné diferentes enfoques para crear una AlertDialogFragmentclase auxiliar genérica que se puede usar exactamente como AlertDialog :


SOLUCIÓN

( TENGA EN CUENTA que estoy usando expresiones lambda de Java 8 en mi código, por lo que es posible que tenga que cambiar partes del código si aún no está usando expresiones lambda ).

/**
 * Helper class for dialog fragments to show a {@link AlertDialog}. It can be used almost exactly
 * like a {@link AlertDialog.Builder}
 * <p />
 * Creation Date: 22.03.16
 *
 * @author felix, http://flx-apps.com/
 */
public class AlertDialogFragment extends DialogFragment {
    protected FragmentActivity activity;
    protected Bundle args;
    protected String tag = AlertDialogFragment.class.getSimpleName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activity = getActivity();
        args = getArguments();
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = setDialogDefaults(new AlertDialog.Builder(getActivity())).create();

        if (args.containsKey("gravity")) {
            dialog.getWindow().getAttributes().gravity = args.getInt("gravity");
        }

        dialog.setOnShowListener(d -> {
            if (dialog != null && dialog.findViewById((android.R.id.message)) != null) {
                ((TextView) dialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
            }
        });
        return dialog;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);

        if (args.containsKey("onDismissListener")) {
            Parcelable onDismissListener = args.getParcelable("onDismissListener");
            if (onDismissListener != null && onDismissListener instanceof ParcelableOnDismissListener) {
                ((ParcelableOnDismissListener) onDismissListener).onDismiss(this);
            }
        }
    }

    /**
     * Sets default dialog properties by arguments which were set using {@link #builder(FragmentActivity)}
     */
    protected AlertDialog.Builder setDialogDefaults(AlertDialog.Builder builder) {
        args = getArguments();
        activity = getActivity();

        if (args.containsKey("title")) {
            builder.setTitle(args.getCharSequence("title"));
        }

        if (args.containsKey("message")) {
            CharSequence message = args.getCharSequence("message");
            builder.setMessage(message);
        }

        if (args.containsKey("viewId")) {
            builder.setView(getActivity().getLayoutInflater().inflate(args.getInt("viewId"), null));
        }

        if (args.containsKey("positiveButtonText")) {
            builder.setPositiveButton(args.getCharSequence("positiveButtonText"), (dialog, which) -> {
                onButtonClicked("positiveButtonListener", which);
            });
        }

        if (args.containsKey("negativeButtonText")) {
            builder.setNegativeButton(args.getCharSequence("negativeButtonText"), (dialog, which) -> {
                onButtonClicked("negativeButtonListener", which);
            });
        }

        if (args.containsKey("neutralButtonText")) {
            builder.setNeutralButton(args.getCharSequence("neutralButtonText"), (dialog, which) -> {
                onButtonClicked("neutralButtonListener", which);
            });
        }

        if (args.containsKey("items")) {
            builder.setItems(args.getStringArray("items"), (dialog, which) -> {
                onButtonClicked("itemClickListener", which);
            });
        }

        // @formatter:off
        // FIXME this a pretty hacky workaround: we don't want to show the dialog if onClickListener of one of the dialog's button click listener were lost
        //       the problem is, that there is no (known) solution for parceling a OnClickListener in the long term (only for state changes like orientation change,
        //       but not if the Activity was completely lost)
        if (
                (args.getParcelable("positiveButtonListener") != null && !(args.getParcelable("positiveButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("negativeButtonListener") != null && !(args.getParcelable("negativeButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("neutralButtonListener") != null && !(args.getParcelable("neutralButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("itemClickListener") != null && !(args.getParcelable("itemClickListener") instanceof ParcelableOnClickListener))
        ) {
            new DebugMessage("Forgot onClickListener. Needs to be dismissed.")
                    .logLevel(DebugMessage.LogLevel.VERBOSE)
                    .show();
            try {
                dismissAllowingStateLoss();
            } catch (NullPointerException | IllegalStateException ignored) {}
        }
        // @formatter:on

        return builder;
    }

    public interface OnDismissListener {
        void onDismiss(AlertDialogFragment dialogFragment);
    }

    public interface OnClickListener {
        void onClick(AlertDialogFragment dialogFragment, int which);
    }

    protected void onButtonClicked(String buttonKey, int which) {
        ParcelableOnClickListener parcelableOnClickListener = getArguments().getParcelable(buttonKey);
        if (parcelableOnClickListener != null) {
            parcelableOnClickListener.onClick(this, which);
        }
    }

    // region Convenience Builder Pattern class almost similar to AlertDialog.Builder
    // =============================================================================================

    public AlertDialogFragment builder(FragmentActivity activity) {
        this.activity = activity;
        this.args = new Bundle();
        return this;
    }

    public AlertDialogFragment addArguments(Bundle bundle) {
        args.putAll(bundle);
        return this;
    }

    public AlertDialogFragment setTitle(int titleStringId) {
        return setTitle(activity.getString(titleStringId));
    }

    public AlertDialogFragment setTitle(CharSequence title) {
        args.putCharSequence("title", title);
        return this;
    }

    public AlertDialogFragment setMessage(int messageStringId) {
        return setMessage(activity.getString(messageStringId));
    }

    public AlertDialogFragment setMessage(CharSequence message) {
        args.putCharSequence("message", message);
        return this;
    }

    public AlertDialogFragment setPositiveButton(int textStringId, OnClickListener onClickListener) {
        return setPositiveButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setPositiveButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("positiveButtonText", text);
        args.putParcelable("positiveButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setNegativeButton(int textStringId, AlertDialogFragment.OnClickListener onClickListener) {
        return setNegativeButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setNegativeButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("negativeButtonText", text);
        args.putParcelable("negativeButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setNeutralButton(int textStringId, AlertDialogFragment.OnClickListener onClickListener) {
        return setNeutralButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setNeutralButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("neutralButtonText", text);
        args.putParcelable("neutralButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setOnDismissListener(OnDismissListener onDismissListener) {
        if (onDismissListener == null) {
            return this;
        }

        Parcelable p = new ParcelableOnDismissListener() {
            @Override
            public void onDismiss(AlertDialogFragment dialogFragment) {
                onDismissListener.onDismiss(dialogFragment);
            }
        };
        args.putParcelable("onDismissListener", p);
        return this;
    }

    public AlertDialogFragment setItems(String[] items, AlertDialogFragment.OnClickListener onClickListener) {
        args.putStringArray("items", items);
        args.putParcelable("itemClickListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setView(int viewId) {
        args.putInt("viewId", viewId);
        return this;
    }

    public AlertDialogFragment setGravity(int gravity) {
        args.putInt("gravity", gravity);
        return this;
    }

    public AlertDialogFragment setTag(String tag) {
        this.tag = tag;
        return this;
    }

    public AlertDialogFragment create() {
        setArguments(args);
        return AlertDialogFragment.this;
    }

    public AlertDialogFragment show() {
        create();
        try {
            super.show(activity.getSupportFragmentManager(), tag);
        }
        catch (IllegalStateException e1) {

            /**
             * this whole part is used in order to attempt to show the dialog if an
             * {@link IllegalStateException} was thrown (it's kinda comparable to
             * {@link FragmentTransaction#commitAllowingStateLoss()} 
             * So you can remove all those dirty hacks if you are sure that you are always
             * properly showing dialogs in the right moments
             */

            new DebugMessage("got IllegalStateException attempting to show dialog. trying to hack around.")
                    .logLevel(DebugMessage.LogLevel.WARN)
                    .exception(e1)
                    .show();

            try {
                Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe");
                mShownByMe.setAccessible(true);
                mShownByMe.set(this, true);
                Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed");
                mDismissed.setAccessible(true);
                mDismissed.set(this, false);
            }
            catch (Exception e2) {
                new DebugMessage("error while showing dialog")
                        .exception(e2)
                        .logLevel(DebugMessage.LogLevel.ERROR)
                        .show();
            }
            FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
            transaction.add(this, tag);
            transaction.commitAllowingStateLoss(); // FIXME hacky and unpredictable workaround
        }
        return AlertDialogFragment.this;
    }

    @Override
    public int show(FragmentTransaction transaction, String tag) {
        throw new NoSuchMethodError("Please use AlertDialogFragment.show()!");
    }

    @Override
    public void show(FragmentManager manager, String tag) {
        throw new NoSuchMethodError("Please use AlertDialogFragment.show()!");
    }

    protected ParcelableOnClickListener createParcelableOnClickListener(AlertDialogFragment.OnClickListener onClickListener) {
        if (onClickListener == null) {
            return null;
        }

        return new ParcelableOnClickListener() {
            @Override
            public void onClick(AlertDialogFragment dialogFragment, int which) {
                onClickListener.onClick(dialogFragment, which);
            }
        };
    }

    /**
     * Parcelable OnClickListener (can be remembered on screen rotation)
     */
    public abstract static class ParcelableOnClickListener extends ResultReceiver implements AlertDialogFragment.OnClickListener {
        public static final Creator<ResultReceiver> CREATOR = ResultReceiver.CREATOR;

        ParcelableOnClickListener() {
            super(null);
        }

        @Override
        public abstract void onClick(AlertDialogFragment dialogFragment, int which);
    }

    /**
     * Parcelable OnDismissListener (can be remembered on screen rotation)
     */
    public abstract static class ParcelableOnDismissListener extends ResultReceiver implements AlertDialogFragment.OnDismissListener {
        public static final Creator<ResultReceiver> CREATOR = ResultReceiver.CREATOR;

        ParcelableOnDismissListener() {
            super(null);
        }

        @Override
        public abstract void onDismiss(AlertDialogFragment dialogFragment);
    }


    // =============================================================================================
    // endregion
}

USO

// showing a normal alert dialog with state loss on configuration changes (like device rotation)
new AlertDialog.Builder(getActivity())
        .setTitle("Are you sure? (1)")
        .setMessage("Do you really want to do this?")
        .setPositiveButton("Yes", (dialog, which) -> Toast.makeText(getContext(), "Yes clicked", Toast.LENGTH_SHORT).show())
        .setNegativeButton("Cancel", null)
        .show();

// showing a dialog fragment using the helper class with no state loss on configuration changes
new AlertDialogFragment.builder(getActivity())
        .setTitle("Are you sure? (2)")
        .setMessage("Do you really want to do this?")
        .setPositiveButton("Yes", (dialog, which) -> Toast.makeText(getContext(), "Yes clicked", Toast.LENGTH_SHORT).show())
        .setNegativeButton("Cancel", null)
        .show();

Estoy publicando esto aquí no solo para compartir mi solución, sino también porque quería pedirles a las personas su opinión: ¿Es este enfoque legítimo o problemático hasta cierto punto?


3
Esta es una idea muy interesante, pero no creo que el diseño de la API funcione. Si pasa un OnClickListener a setPositiveButton (), cuando el dispositivo se gira y el fragmento se vuelve a crear a partir de los argumentos Bundle, los OnClickListeners no se volverán a crear correctamente desde el Parcelable. El problema fundamental es que no puede recrear un escucha durante la rotación, pero la interfaz API (que toma interfaces) lo exige. Desearía que este no fuera el caso (como me gusta la idea).
Xargs

1
Buena idea, pero como dice @Xargs, no funciona. Los oyentes pasados ​​no se recrean correctamente en la rotación.
Graham Borland

Mis resultados son que realmente funciona en la rotación y en la reanudación de la aplicación (después de ir a la pantalla de inicio, por ejemplo), pero no cuando la actividad se restaura después de que se ha destruido por completo (entonces los OnClickListeners se pierden). (Probado en Android 4.4.4 y Android 5.1.1)
flxapps

No he probado esta implementación exacta, pero por lo que he probado, un oyente parcelable pasado a un paquete de fragmentos se llama correctamente al recrear. No tengo idea de por qué, pero parece funcionar.
Saad Farooq

@flxapps, en el caso de una vista personalizada, ¿cómo puede obtener las vistas secundarias y cambiar sus propiedades o aplicar oyentes? En su clase no está devolviendo ninguna instancia de diálogo y eso podría causar una excepción si alguien intenta obtener vistas de los niños
Zubair Rehman

5

¿Puedo sugerir una pequeña simplificación de la respuesta de @ ashishduh:

public class AlertDialogFragment extends DialogFragment {
public static final String ARG_TITLE = "AlertDialog.Title";
public static final String ARG_MESSAGE = "AlertDialog.Message";

public static void showAlert(String title, String message, Fragment targetFragment) {
    DialogFragment dialog = new AlertDialogFragment();
    Bundle args = new Bundle();
    args.putString(ARG_TITLE, title);
    args.putString(ARG_MESSAGE, message);
    dialog.setArguments(args);
    dialog.setTargetFragment(targetFragment, 0);
    dialog.show(targetFragment.getFragmentManager(), "tag");
}

public AlertDialogFragment() {}

@NonNull
@Override
public AlertDialog onCreateDialog(Bundle savedInstanceState)
{
    Bundle args = getArguments();
    String title = args.getString(ARG_TITLE, "");
    String message = args.getString(ARG_MESSAGE, "");

    return new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                }
            })
            .create();
}

Elimina la necesidad de que el usuario (de la clase) esté familiarizado con los componentes internos del componente y hace que el uso sea realmente simple:

AlertDialogFragment.showAlert(title, message, this);

PD: En mi caso, necesitaba un diálogo de alerta simple, así que eso fue lo que creé. Puede aplicar el enfoque a un Sí / No o cualquier otro tipo que necesite.


1

Utilice Diálogo para cuadros de diálogo simples de sí o no.

Cuando necesite vistas más complejas en las que necesite obtener el ciclo de vida, como oncreate, solicitar permisos, cualquier anulación del ciclo de vida, usaría un fragmento de diálogo. Por lo tanto, separa los permisos y cualquier otro código que el diálogo necesita para operar sin tener que comunicarse con la actividad de llamada.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.