How can I reuse an AlertDialog for Yes/No on Android?

前端 未结 2 1044
说谎
说谎 2021-02-04 18:49

I\'m trying to find the way to reuse a Dialog that shows customized titles, then send the Yes/No click to the function that has launched the Dialog.

I have two buttoms,

2条回答
  •  有刺的猬
    2021-02-04 19:45

    Since this page is the first hit on Google, and it seems like such a common task with so little written about it, I'll share the way I've found to show a reusable DialogFragment.

    Using interfaces gets really messy if you want to reuse the same Dialog multiple times from the same class, but perform a different action everytime. This solution is a simple and straight-forward way to get around that issue without introducing any disadvantages.

    Edit 2017-02-25: This answer was previously using an Abstract class to implement confirm() and cancel(), however newer versions of Android will crash with the following error if you try to use an anonymous class as a DialogFragment:

    java.lang.IllegalStateException: Fragment null must be a public static class to be properly recreated from instance state.

    so I've modified the solution to use Runnables, which works really nice in Java8 but is also feasible without it

    First, create a class which implements the creation of the Dialog itself:

    /**
     * This is a reusable convenience class which makes it easy to show a confirmation dialog as a DialogFragment.
     * Create a new instance, call setArgs(...), setConfirm(), and setCancel() then show it via the fragment manager as usual.
     */
    public class ConfirmationDialog extends DialogFragment {
        // Do nothing by default
        private Runnable mConfirm = new Runnable() {
            @Override
            public void run() {
            }
        };
        // Do nothing by default
        private Runnable mCancel = new Runnable() {
            @Override
            public void run() {
            }
        };
    
        public void setArgs(String message) {
            setArgs("" , message);
        }
    
        public void setArgs(String title, String message) {
            Bundle args = new Bundle();
            args.putString("message", message);
            args.putString("title", title);
            setArguments(args);
        }
    
        public void setConfirm(Runnable confirm) {
            mConfirm = confirm;
        }
    
        public void setCancel(Runnable cancel) {
            mCancel = cancel;
        }
    
        @Override
        public MaterialDialog onCreateDialog(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Resources res = getActivity().getResources();
            String title = getArguments().getString("title");
            return new MaterialDialog.Builder(getActivity())
                    .title(title.equals("") ? res.getString(R.string.app_name) : title)
                    .content(getArguments().getString("message"))
                    .positiveText(res.getString(R.string.dialog_ok))
                    .negativeText(res.getString(R.string.dialog_cancel))
                    .callback(new MaterialDialog.ButtonCallback() {
                        @Override
                        public void onPositive(MaterialDialog dialog) {
                            mConfirm.run();
                        }
    
                        @Override
                        public void onNegative(MaterialDialog dialog) {
                            mCancel.run();
                        }
                    })
                    .show();
        }
    }
    

    Secondly, you should make a common method in your Activity which shows a DialogFragment using the fragment manager:

    /**
     * Global method to show dialog fragment
     * @param newFragment  the DialogFragment you want to show
     */
    public void showDialogFragment(DialogFragment newFragment) {
        // DialogFragment.show() will take care of adding the fragment
        // in a transaction. We also want to remove any currently showing
        // dialog, so make our own transaction and take care of that here.
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
        if (prev != null) {
            ft.remove(prev);
        }
        // save transaction to the back stack
        ft.addToBackStack("dialog");
        newFragment.show(ft, "dialog");
    }
    

    Then you can show a confirmation dialog from anywhere in your Activity like this:

    ConfirmationDialog dialog = new ConfirmationDialog ();
    dialog.setArgs(stringDialogTitle, stringDialogMessage);
    Runnable confirm = new Runnable() {
        @Override
        public void run() {
            doStuff();
        }
    };
    dialog.setConfirm(confirm);
    showDialogFragment(dialog);
    

    If you have Java8 you can use lambdas for the functions which will make the code much less verbose. See here for an example.

提交回复
热议问题