How to prevent a dialog from closing when a button is clicked

后端 未结 18 2230
无人及你
无人及你 2020-11-21 23:59

I have a dialog with EditText for input. When I click the \"yes\" button on dialog, it will validate the input and then close the dialog. However, if the input

18条回答
  •  孤街浪徒
    2020-11-22 00:42

    I've written a simple class (an AlertDialogBuilder) that you can use to disable the auto-dismiss feature when pressing the dialog's buttons.

    It is compatible also with Android 1.6, so it doesn't make use of the OnShowListener (which is available only API >= 8).

    So, instead of using AlertDialog.Builder you can use this CustomAlertDialogBuilder. The most important part is that you should not call create(), but only the show() method. I've added methods like setCanceledOnTouchOutside() and setOnDismissListener so that you can still set them directly on the builder.

    I tested it on Android 1.6, 2.x, 3.x and 4.x so it should work pretty well. If you find some problems please comment here.

    package com.droidahead.lib.utils;
    
    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.view.View;
    import android.view.View.OnClickListener;
    
    public class CustomAlertDialogBuilder extends AlertDialog.Builder {
        /**
         * Click listeners
         */
        private DialogInterface.OnClickListener mPositiveButtonListener = null;
        private DialogInterface.OnClickListener mNegativeButtonListener = null;
        private DialogInterface.OnClickListener mNeutralButtonListener = null;
    
        /**
         * Buttons text
         */
        private CharSequence mPositiveButtonText = null;
        private CharSequence mNegativeButtonText = null;
        private CharSequence mNeutralButtonText = null;
    
        private DialogInterface.OnDismissListener mOnDismissListener = null;
    
        private Boolean mCancelOnTouchOutside = null;
    
        public CustomAlertDialogBuilder(Context context) {
            super(context);
        }
    
        public CustomAlertDialogBuilder setOnDismissListener (DialogInterface.OnDismissListener listener) {
            mOnDismissListener = listener;
            return this;
        }
    
        @Override
        public CustomAlertDialogBuilder setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) {
            mNegativeButtonListener = listener;
            mNegativeButtonText = text;
            return this;
        }
    
        @Override
        public CustomAlertDialogBuilder setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) {
            mNeutralButtonListener = listener;
            mNeutralButtonText = text;
            return this;
        }
    
        @Override
        public CustomAlertDialogBuilder setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) {
            mPositiveButtonListener = listener;
            mPositiveButtonText = text;
            return this;
        }
    
        @Override
        public CustomAlertDialogBuilder setNegativeButton(int textId, DialogInterface.OnClickListener listener) {
            setNegativeButton(getContext().getString(textId), listener);
            return this;
        }
    
        @Override
        public CustomAlertDialogBuilder setNeutralButton(int textId, DialogInterface.OnClickListener listener) {
            setNeutralButton(getContext().getString(textId), listener);
            return this;
        }
    
        @Override
        public CustomAlertDialogBuilder setPositiveButton(int textId, DialogInterface.OnClickListener listener) {
            setPositiveButton(getContext().getString(textId), listener);
            return this;
        }
    
        public CustomAlertDialogBuilder setCanceledOnTouchOutside (boolean cancelOnTouchOutside) {
            mCancelOnTouchOutside = cancelOnTouchOutside;
            return this;
        }
    
    
    
        @Override
        public AlertDialog create() {
            throw new UnsupportedOperationException("CustomAlertDialogBuilder.create(): use show() instead..");
        }
    
        @Override
        public AlertDialog show() {
            final AlertDialog alertDialog = super.create();
    
            DialogInterface.OnClickListener emptyOnClickListener = new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) { }
            };
    
    
            // Enable buttons (needed for Android 1.6) - otherwise later getButton() returns null
            if (mPositiveButtonText != null) {
                alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, mPositiveButtonText, emptyOnClickListener);
            }
    
            if (mNegativeButtonText != null) {
                alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, mNegativeButtonText, emptyOnClickListener);
            }
    
            if (mNeutralButtonText != null) {
                alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, mNeutralButtonText, emptyOnClickListener);
            }
    
            // Set OnDismissListener if available
            if (mOnDismissListener != null) {
                alertDialog.setOnDismissListener(mOnDismissListener);
            }
    
            if (mCancelOnTouchOutside != null) {
                alertDialog.setCanceledOnTouchOutside(mCancelOnTouchOutside);
            }
    
            alertDialog.show();
    
            // Set the OnClickListener directly on the Button object, avoiding the auto-dismiss feature
            // IMPORTANT: this must be after alert.show(), otherwise the button doesn't exist..
            // If the listeners are null don't do anything so that they will still dismiss the dialog when clicked
            if (mPositiveButtonListener != null) {
                alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new OnClickListener() {
    
                    @Override
                    public void onClick(View v) {
                        mPositiveButtonListener.onClick(alertDialog, AlertDialog.BUTTON_POSITIVE);
                    }
                });
            }
    
            if (mNegativeButtonListener != null) {
                alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new OnClickListener() {
    
                    @Override
                    public void onClick(View v) {
                        mNegativeButtonListener.onClick(alertDialog, AlertDialog.BUTTON_NEGATIVE);
                    }
                });
            }
    
            if (mNeutralButtonListener != null) {
                alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() {
    
                    @Override
                    public void onClick(View v) {
                        mNeutralButtonListener.onClick(alertDialog, AlertDialog.BUTTON_NEUTRAL);
                    }
                });
            }
    
            return alertDialog;
        }   
    }
    

    EDIT Here is a small example on how to use the CustomAlertDialogBuilder:

    // Create the CustomAlertDialogBuilder
    CustomAlertDialogBuilder dialogBuilder = new CustomAlertDialogBuilder(context);
    
    // Set the usual data, as you would do with AlertDialog.Builder
    dialogBuilder.setIcon(R.drawable.icon);
    dialogBuilder.setTitle("Dialog title");
    dialogBuilder.setMessage("Some text..");
    
    // Set your buttons OnClickListeners
    dialogBuilder.setPositiveButton ("Button 1", new DialogInterface.OnClickListener() {
        public void onClick (DialogInterface dialog, int which) {
            // Do something...
    
            // Dialog will not dismiss when the button is clicked
            // call dialog.dismiss() to actually dismiss it.
        }
    });
    
    // By passing null as the OnClickListener the dialog will dismiss when the button is clicked.               
    dialogBuilder.setNegativeButton ("Close", null);
    
    // Set the OnDismissListener (if you need it)       
    dialogBuilder.setOnDismissListener(new DialogInterface.OnDismissListener() {
        public void onDismiss(DialogInterface dialog) {
            // dialog was just dismissed..
        }
    });
    
    // (optional) set whether to dismiss dialog when touching outside
    dialogBuilder.setCanceledOnTouchOutside(false);
    
    // Show the dialog
    dialogBuilder.show();
    

    Cheers,

    Yuvi

提交回复
热议问题