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

后端 未结 18 1954
无人及你
无人及你 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:32

    If you are using material design I would suggest checking out material-dialogs. It fixed several issues for me related to currently open Android bugs (see 78088), but most importantly for this ticket it has an autoDismiss flag that can be set when using the Builder.

    0 讨论(0)
  • 2020-11-22 00:33

    For ProgressDialogs

    To prevent the dialog from being dismissed automatically you have to set the OnClickListener after the ProgressDialog is shown, like so:

    connectingDialog = new ProgressDialog(this);
    
    connectingDialog.setCancelable(false);
    connectingDialog.setCanceledOnTouchOutside(false);
    
    // Create the button but set the listener to a null object.
    connectingDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", 
            (DialogInterface.OnClickListener) null )
    
    // Show the dialog so we can then get the button from the view.
    connectingDialog.show();
    
    // Get the button from the view.
    Button dialogButton = connectingDialog.getButton( DialogInterface.BUTTON_NEGATIVE);
    
    // Set the onClickListener here, in the view.
    dialogButton.setOnClickListener( new View.OnClickListener() {
    
        @Override
        public void onClick ( View v ) {
    
            // Dialog will not get dismissed until you call dismiss() explicitly.
    
        }
    
    });
    
    0 讨论(0)
  • 2020-11-22 00:40

    EDIT: This only works on API 8+ as noted by some of the comments.

    This is a late answer, but you can add an onShowListener to the AlertDialog where you can then override the onClickListener of the button.

    final AlertDialog dialog = new AlertDialog.Builder(context)
            .setView(v)
            .setTitle(R.string.my_title)
            .setPositiveButton(android.R.string.ok, null) //Set to null. We override the onclick
            .setNegativeButton(android.R.string.cancel, null)
            .create();
    
    dialog.setOnShowListener(new DialogInterface.OnShowListener() {
    
        @Override
        public void onShow(DialogInterface dialogInterface) {
    
            Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
            button.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View view) {
                    // TODO Do something
    
                    //Dismiss once everything is OK.
                    dialog.dismiss();
                }
            });
        }
    });
    dialog.show();
    
    0 讨论(0)
  • 2020-11-22 00:40

    Here's something if you are using DialogFragment - which is the recommended way to handle Dialogs anyway.

    What happens with AlertDialog's setButton() method (and I imagine the same with AlertDialogBuilder's setPositiveButton() and setNegativeButton()) is that the button you set (e.g. AlertDialog.BUTTON_POSITIVE) with it will actually trigger TWO different OnClickListener objects when pressed.

    The first being DialogInterface.OnClickListener, which is a parameter to setButton(), setPositiveButton(), and setNegativeButton().

    The other is View.OnClickListener, which will be set to automatically dismiss your AlertDialog when any of its button is pressed - and is set by AlertDialog itself.

    What you can do is to use setButton() with null as the DialogInterface.OnClickListener, to create the button, and then call your custom action method inside View.OnClickListener. For example,

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        AlertDialog alertDialog = new AlertDialog(getActivity());
        // set more items...
        alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", null);
    
        return alertDialog;
    }
    

    Then, you may override the default AlertDialog's buttons' View.OnClickListener (which would otherwise dismiss the dialog) in the DialogFragment's onResume() method:

    @Override
    public void onResume()
    {
        super.onResume();
        AlertDialog alertDialog = (AlertDialog) getDialog();
        Button okButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
        okButton.setOnClickListener(new View.OnClickListener() { 
            @Override
            public void onClick(View v)
            {
                performOkButtonAction();
            }
        });
    }
    
    private void performOkButtonAction() {
        // Do your stuff here
    }
    

    You will need to set this in the onResume() method because getButton() will return null until after the dialog has been shown!

    This should cause your custom action method to only be called once, and the dialog won't be dismissed by default.

    0 讨论(0)
  • 2020-11-22 00:40

    Kotlin

    val dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_userinput, null)
            val dialogBuilder = MaterialAlertDialogBuilder(requireContext(), R.style.AlertDialogTheme)
       
            dialogBuilder.setView(dialogView)
            dialogBuilder.setCancelable(false)
            dialogBuilder.setPositiveButton("send",null)
            dialogBuilder.setNegativeButton("cancel") { dialog,_ ->
            dialog.dismiss()
            }
    
    
            val alertDialog = dialogBuilder.create()
            alertDialog.show()
    
            val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
            positiveButton.setOnClickListener {
                val myInputText = dialogView.etxt_userinput.text.toString().trim()
                if(myInputText.isNotEmpty()){
                 //Do something
                }else{
                    //Prompt error
                    dialogView.etxt_userinput.error = "Please fill this"
                }
            }
    

    We just create an AlertDialog with the dialogBuilder and then just set the positive button as we want

    0 讨论(0)
  • 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

    0 讨论(0)
提交回复
热议问题