【问题标题】:Android Confirmation dialog returning true or falseAndroid 确认对话框返回 true 或 false
【发布时间】:2012-06-01 14:25:36
【问题描述】:

似乎没有简单的方法让警报对话框返回一个简单的值。
此代码不起作用answer 变量无法从侦听器中设置,实际上它甚至无法编译)

public static boolean Confirm(Context context) {
    boolean answer;
    AlertDialog dialog = new AlertDialog.Builder(context).create();
    dialog.setTitle("Confirmation");
    dialog.setMessage("Choose Yes or No");
    dialog.setCancelable(false);
    dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int buttonId) {
            answer = true;
        }
    });
    dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "No", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int buttonId) {
            answer = false;
        }
    });
    dialog.setIcon(android.R.drawable.ic_dialog_alert);
    dialog.show();
    return answer;
}

注意:方法是自包含的,即它不依赖于变量或外部构造,这一点很重要。只需调用它并得到你的答案,无论是真是假。

那么,该怎么办?这个返回 truefalse 的简单愿望似乎比它应得的要复杂得多。

另外,setButton 方法具有以下形式:

dialog.setButton(int buttonId, String buttonText, Message msg)

但不清楚如何使用,消息发送到哪里,发给谁,使用哪个处理程序?

【问题讨论】:

    标签: android dialog confirmation


    【解决方案1】:

    我在这个论坛上发布了类似的问题,但最后我得到了答案。 我在那篇文章中的问题是如何创建可以通过其他类或活动访问的单独确认对话框类,因此使用该确认对话框类我们不需要编写长代码。

    这是我的答案。

    首先你必须创建DialogHandler.java

    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import src.app.R;
    
    public class DialogHandler {
        public Runnable ans_true = null;
        public Runnable ans_false = null;
    
        // Dialog. --------------------------------------------------------------
    
        public boolean Confirm(Activity act, String Title, String ConfirmText,
                String CancelBtn, String OkBtn, Runnable aProcedure, Runnable bProcedure) {
            ans_true = aProcedure;
            ans_false= bProcedure;
            AlertDialog dialog = new AlertDialog.Builder(act).create();
            dialog.setTitle(Title);
            dialog.setMessage(ConfirmText);
            dialog.setCancelable(false);
            dialog.setButton(DialogInterface.BUTTON_POSITIVE, OkBtn,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int buttonId) {
                             ans_true.run();
                        }
                    });
            dialog.setButton(DialogInterface.BUTTON_NEGATIVE, CancelBtn,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int buttonId) {
                            ans_false.run();
                        }
                    });
            dialog.setIcon(android.R.drawable.ic_dialog_alert);
            dialog.show();
            return true;
        }
    }
    

    这是在另一个类中调用它的示例

    public class YourActivity extends Activity {
        /** Called when the activity is first created. */
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            findViewById(R.id.button1).setOnClickListener(myclick);
        }
    
        public final Button.OnClickListener myclick = new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                doclick();
            }
        };
    
        public void doclick() {
            DialogHandler appdialog = new DialogHandler();
            appdialog.Confirm(this, "Message title", "Message content",
                    "Cancel", "OK", aproc(), bproc());
        }
    
        public Runnable aproc(){
            return new Runnable() {
                public void run() {
                    Log.d("Test", "This from A proc");
                }
              };
        }
    
        public Runnable bproc(){
            return new Runnable() {
                public void run() {
                    Log.d("Test", "This from B proc");
                }
              };
        }
    
    
    }
    

    【讨论】:

    • @Lion789 在我自己的回答中查看我对您的评论的回复。真正的测试是:在onClick() 方法中放入一些代码after 调用doClick() 来检查用户对DialogHandler 对话框的响应,并查看代码执行是否等待对话框关闭.我认为不会。
    • 我喜欢你的方法,它正在运行。我已经检查过了。
    • @Roro 干得好。有用。这应该是公认的答案
    • @AsepRoro 不错的逻辑......工作得很好。这确实需要成为公认的答案。
    【解决方案2】:

    好吧,我想说我对自己很满意,因为我自己找到了一个简单的答案!
    但事实是,虽然我找到了一种返回值的方法(如下所示)。 没有用

    真正的问题是我想要一个同步对话框,该对话框在 dialog.show() 之后恢复您的代码之前等待用户回答。
    Android 中没有这样的野兽。所有对话都是异步的,所以dialog.show() 只在某个队列中发布对话(我认为)并继续。因此,您无法及时得到答案。

    尽管它的所有价值(没有),您将在下面找到如何在构建对话框的方法中设置一个值。也许这种技术还有其他用途,与对话生命周期无关。




    为了提供一些相关信息,我会说如果你替换

    boolean answer;
    

    final boolean answer;
    

    可以从侦听器中访问该变量,但不能为其分配新值,因为它被声明为 final

    诀窍来了。
    将变量定义为:

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

    你们中的一些人已经明白为什么这会奏效。这里的最终变量不是布尔数组的单个元素,而是数组本身。
    所以现在您可以根据需要分配数组元素 [0]。

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

    最后你可以从你的方法中返回它。

    【讨论】:

    • 您找到更好的解决方案了吗?
    • @Lion789 正如我所说,这并不是一个真正的解决方案,我解释了为什么使用当前的 Android 操作系统不能有灵魂。所以,简而言之,我没有找到更好的解决方案。根据 Android,您应该将代码放在对话框的 onClick() 侦听器中。这是关闭对话框后执行它的唯一方法。
    • iLomambo 你有没有尝试过调用 Runnable 的方法
    • 我已经转移到其他项目,所以我没有尝试过。但是,如果您理解我的回答,那么它的行为方式就很明显了。由于Android的异步特性,在你调用show()的那一刻,对话框就会显示出来,代码继续,它不会等待用户点击@987654328 @
    • 对,但是如果代码中没有其他内容,例如 onClick(dialog(proca(), procb()) 屏幕只会在选择后更改,而不管异步如何,因为在 procA 我告诉它除非被告知在对话框中运行,否则该做什么并且不会被执行
    【解决方案3】:

    您可以做的是为您的警报对话框创建一个侦听器,该侦听器使用接口侦听 AlertDialogs 操作。

    创建一个接口。

    public class MyInterface {
    
        DialogReturn dialogReturn;
    
        public interface DialogReturn {
    
            void onDialogCompleted(boolean answer);
        }
    
        public void setListener(DialogReturn dialogReturn) {
            this.dialogReturn = dialogReturn;
        }
    
        public DialogReturn getListener() {
            return dialogReturn;
    
        }
    }
    

    现在,在你的类中实现你使用implements MyInterface.DialogReturn创建的接口

    然后您可以设置监听器并使其工作,如下所示,

    public class Main extends Activity implements MyInterface.DialogReturn{
    
        MyInterface myInterface;
        MyInterface.DialogReturn dialogReturn;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
                    ....
            myInterface = new MyInterface();
            myInterface.setListener(this);
        }
    
    
       public void Confirm(Context context) {
            AlertDialog dialog = new AlertDialog.Builder(context).create();
            dialog.setTitle("Confirmation");
            dialog.setMessage("Choose Yes or No");
            dialog.setCancelable(false);
            dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int buttonId) {
                    myInterface.getListener().onDialogCompleted(true);
                }
            });
            dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int buttonId) {
                    myInterface.getListener().onDialogCompleted(false);
                }
            });
            dialog.setIcon(android.R.drawable.ic_dialog_alert);
            dialog.show();
             }
    
    
    @Override
        public void onDialogCompleted(boolean answer) {
            Toast.makeText(Main.this, answer+"", Toast.LENGTH_LONG).show();
                if(answer)
                // do something
                else
                // do something
        }
    }
    

    【讨论】:

    • 我假设您的建议有效。但是,实现简单事情的方法多么复杂!你不觉得吗?
    • 是的,但如果我们理解一次并让它发挥作用,这并没有那么复杂。
    • @ilomambo 欢迎使用 Android!欢迎使用 Java。
    【解决方案4】:

    我发现使用 jDeferred 在您想要等待输入的情况下会有所帮助。

    它本质上等同于使用接口,但是您创建完成和失败处理程序。只是一个可供考虑的替代方案:

    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) {
                    ...
                }
            });
    

    实施:

    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();
        }
    
    }
    

    【讨论】:

      【解决方案5】:

      对于 Andriod,等待用户说“是”或“否”来阻止正在运行的线程并不是一个好主意。

      为了请求确认,您可以定义一个接收 AsynTask 的方法。如果用户按下确认按钮,该方法将执行该任务。

      例如:

          //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();
      }
      

      你可以从你的活动中调用它:

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

      YourTask 类必须扩展 AsyncTask

      【讨论】:

        【解决方案6】:

        在您的活动中声明一个字段“答案”并为其设置一个值。类的字段对内部类是可见的,因此您可以这样做。

        【讨论】:

        • 是的..我没有提到它,但我需要方法独立于它定义的类。不能使用类变量。我将更新问题以使其更清楚。
        【解决方案7】:

        我也在努力使用阻止确认对话框,我终于使用 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;
                }
        
            }
        }
        

        【讨论】:

          【解决方案8】:

          在我看来,我已经尝试了所有的解决方案,并且最简单和最干净的是迄今为止第一个使用 Runnable 的解决方案。它支持取消按钮侦听器上的对话框,On​​BAckPressed() 和 onOptionsItemSelected()。

          所描述的代码虽然调用了 ans_false.run();单击 BUTTON_POSITIVE 和 ans_true.run() 时;单击 BUTTON_NEGATIVE 时。

          这是我用来解决这个问题的代码:

          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;
          }
          

          }

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-05-29
            • 1970-01-01
            • 2011-01-17
            • 1970-01-01
            • 1970-01-01
            • 2014-06-03
            • 1970-01-01
            相关资源
            最近更新 更多