Android Confirmation dialog returning true or false

前端 未结 8 1228
不知归路
不知归路 2020-12-09 05:40

It seems to be there is no easy way to get an Alert dialog to return a simple value.
This code does not work (the answer variable cannot be set

相关标签:
8条回答
  • 2020-12-09 05:50

    I was also struggling to use a blocking confirm dialog and I finally did it using a BlockingQueue :

    public static class BlockingConfirmDialog{
    
        private Activity context;
    
        BlockingQueue<Boolean> blockingQueue;
    
        public BlockingConfirmDialog(Activity activity) {
            super();
            this.context = activity;
            blockingQueue = new ArrayBlockingQueue<Boolean>(1);
        }
    
        public boolean confirm(final String title, final String message){
    
            context.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    new AlertDialog.Builder(context)
                    .setTitle(title)
                    .setMessage(message)
                    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) { 
                            blockingQueue.add(true);
                        }
                     })
                     .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            blockingQueue.add(false);
                        }
                    })
                     .show();
                }
            });
    
            try {
                return blockingQueue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
                return false;
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-12-09 05:50

    I've tried all of the solutions and the easier and cleanest is by far the first solution with the Runnable, in my opinion. It supports the dialog on the Cancel button listener, the OnBAckPressed() and the onOptionsItemSelected().

    The code as described though calls the ans_false.run(); when clicking the BUTTON_POSITIVE and the ans_true.run(); when clicking the BUTTON_NEGATIVE.

    Here is the code I used to fix that problem:

    public class MyDialogs {
    
    // private constructor
    public Runnable answerTrue = null;
    public Runnable answerFalse = null;
    
    // Dialog. --------------------------------------------------------------
    
    public boolean confirm(Activity act, String Title, String ConfirmText,
                           String noBtn, String yesBtn, Runnable yesProc, Runnable noProc) {
        answerTrue = yesProc;
        answerFalse= noProc;
        AlertDialog.Builder alert = new AlertDialog.Builder(act);
        alert.setTitle(Title);
        alert.setMessage(ConfirmText);
        alert.setCancelable(false);
        alert.setPositiveButton(R.string.button_positive, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                answerTrue.run();
            }
        });
        alert.setNegativeButton(R.string.button_negative, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                answerFalse.run();
            }
        });
        alert.show().getButton(DialogInterface.BUTTON_NEGATIVE).requestFocus();
        return true;
    }
    

    }

    0 讨论(0)
  • 2020-12-09 06:00

    I find that using jDeferred helps in cases where you want to wait for input.

    It is essentially equivalent to using an interface, but instead you create done and fail handlers. Just an alternative to consider:

    new ConfirmationDialog(mContext)
            .showConfirmation("Are you sure?", "Yes", "No")
            .done(new DoneCallback<Void>() {
                @Override
                public void onDone(Void aVoid) {
                    ....
                }
            })
            .fail(new FailCallback<Void>() {
    
                @Override
                public void onFail(Void aVoid) {
                    ...
                }
            });
    

    Implementation:

    public class ConfirmationDialog {
    
    
        private final Context mContext;
        private final DeferredObject<Void, Void, Void> mDeferred = new DeferredObject<Void, Void, Void>();
    
        public ConfirmationDialog(Context context) {
            mContext = context;
        }
    
        public Promise<Void, Void, Void> showConfirmation(String message, String positiveButton, String negativeButton) {
            AlertDialog dialog = new AlertDialog.Builder(mContext).create();
            dialog.setTitle("Alert");
            dialog.setMessage(message);
            dialog.setCancelable(false);
            dialog.setButton(DialogInterface.BUTTON_POSITIVE, positiveButton, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int buttonId) {
                    mDeferred.resolve(null);
                }
            });
            dialog.setButton(DialogInterface.BUTTON_NEGATIVE, negativeButton, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int buttonId) {
                    mDeferred.reject(null);
                }
            });
            dialog.setIcon(android.R.drawable.ic_dialog_alert);
            dialog.show();
            return mDeferred.promise();
        }
    
    }
    
    0 讨论(0)
  • 2020-12-09 06:06

    Well, I was going to say that I am very pleased with myself because I found a simple answer, all by myself!
    But the truth is that although I find a way to return a value (which I show below). It is of no use.

    The real problem is I wanted a synchronous Dialog, a dialog that waits for the user to answer before resuming your code after dialog.show().
    There is no such beast in Android. All dialogs are asynchronous, so dialog.show() only posts the dialog in some queue (I think) and continues. Thus you don't get your answer in time.

    For all its worth (nothing) below you'll find how to set a value inside the method that builds the dialog. Maybe there are other uses for this technique, not related to the dialog lifecycle.




    To give some related info, I'll say that if you replace

    boolean answer;
    

    with

    final boolean answer;
    

    it is possible to access the variable from within the listener, but it is not possible to assign it a new value, since it was declared as final.

    Here comes the trick.
    Define the variable as:

    final boolean[] answer = new boolean[1];
    

    Some of you already see why this will work. The final variable here is not the single element of the boolean array, is the array itself.
    So now you can assign the array element [0] as you wish.

    dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int buttonId) {
            answer[0] = true;
        }
    });
    . . .
    return answer[0];
    

    And finally you can return it from your method.

    0 讨论(0)
  • 2020-12-09 06:07

    With Andriod, it is not a good idea to block the running thread by waiting for the user to say 'yes' or 'no'.

    In order to ask for a confirmation, you can define a method that receives an AsynTask. The method executes that task if the user press the confirm button.

    For example:

        //this method displays a confirm dialog. If 'yes' answer, runs 'yesTask', 
        //if 'no' answer, runs 'noTask'
        //notice than 'yesTask' and 'noTask' are AysncTask
        //'noTask' can be null, example: if you want to cancel when 'no answer'
    
        public static void confirm(Activity act, String title, String confirmText,
                           String noButtonText, String yesButtonText,
                           final AsyncTask<String, Void, Boolean> yesTask,
                           final AsyncTask<String, Void, Boolean> noTask) {
    
        AlertDialog dialog = new AlertDialog.Builder(act).create();
        dialog.setTitle(title);
        dialog.setMessage(confirmText);
        dialog.setCancelable(false);
        dialog.setButton(DialogInterface.BUTTON_POSITIVE, yesButtonText,
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int buttonId) {
                    yesTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                }
            });
        dialog.setButton(DialogInterface.BUTTON_NEGATIVE, noButtonText,
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int buttonId) {
                    if(noTask!=null) {
                        noTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                    }
    
                }
            });
        dialog.setIcon(android.R.drawable.ic_dialog_alert);
        dialog.show();
    }
    

    You can call it from your activity with:

     YourTask yourTask =  new YourTask( ... );
     confirm( YourActivity.this, 
             "Confirm", 
             "Are you sure?", 
             "Cancel", 
             "Continue", 
             yourTask,
             null);
    

    YourTask class must extend AsyncTask

    0 讨论(0)
  • 2020-12-09 06:09

    Declare a field 'answer' in your activity and set a value to it. Fields of a class are visible to inner classes, so you can do that.

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