2012-05-26 42 views
9

Có vẻ như không có cách nào dễ dàng để có được hộp thoại Alert để trả về một giá trị đơn giản.
này đang không hoạt động (các câu trả lời biến không thể được thiết lập từ bên trong người nghe, trên thực tế nó thậm chí không biên dịch)Hộp thoại xác nhận Android trả về true hoặc false

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

Chú ý: Điều quan trọng là phương pháp này là tự chứa, tức là, nó không phụ thuộc vào các biến hoặc cấu trúc bên ngoài vào nó. Chỉ cần gọi nó và nhận được câu trả lời của bạn, đúng hay sai.

Vì vậy, phải làm gì? Mong muốn đơn giản này là trả lại đúng hoặc false dường như phức tạp hơn nhiều so với giá trị của nó.

Ngoài ra, phương pháp setButton có dạng:

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

Nhưng nó không phải là rõ ràng làm thế nào để sử dụng nó, mà là meesage gửi đến, cho ai, mà xử lý được sử dụng?

Trả lời

9

Vâng, tôi đã sẽ nói rằng tôi rất hài lòng với bản thân mình bởi vì tôi đã tìm thấy một câu trả lời đơn giản, tất cả bởi bản thân mình!
Nhưng sự thật là mặc dù tôi tìm cách trả lại giá trị (mà tôi hiển thị bên dưới). Không sử dụng.

Vấn đề thực sự là tôi muốn hộp thoại đồng bộ, hộp thoại chờ người dùng trả lời trước khi tiếp tục mã của bạn sau dialog.show().
Không có con thú nào trong Android. Tất cả các hộp thoại đều không đồng bộ, do đó, dialog.show() chỉ đăng hộp thoại trong một số hàng đợi (tôi nghĩ) và tiếp tục. Vì vậy, bạn không nhận được câu trả lời của bạn trong thời gian.

Đối với tất cả giá trị của nó (không có gì) bên dưới, bạn sẽ tìm cách đặt giá trị bên trong phương thức xây dựng hộp thoại. Có thể có những cách sử dụng khác cho kỹ thuật này, không liên quan đến vòng đời của hộp thoại.




Để cung cấp một số thông tin có liên quan, tôi sẽ nói rằng nếu bạn thay thế

boolean answer; 

với

final boolean answer; 

nó có thể truy cập vào biến từ bên trong người nghe, nhưng không thể gán cho nó một giá trị mới, kể từ khi nó được tuyên bố là cuối cùng.

Đây là mẹo.
Xác định các biến như:

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

Một số bạn đã thấy tại sao điều này sẽ làm việc. Biến cuối cùng ở đây không phải là phần tử đơn của mảng boolean, là chính mảng đó.
Vì vậy, bây giờ bạn có thể gán phần tử mảng [0] như bạn muốn.

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

Và cuối cùng bạn có thể trả lại từ phương thức của mình.

+0

Bạn đã bao giờ tìm được giải pháp tốt hơn chưa? – Lion789

+1

@ Lion789 Như tôi đã nói, đây không phải là giải pháp thực sự và tôi đã giải thích lý do tại sao với hệ điều hành Android hiện tại không thể có linh hồn. Vì vậy, trong ngắn hạn, tôi đã không tìm thấy một giải pháp tốt hơn. Theo Android, bạn nên đặt mã của mình bên trong trình nghe onClick() cho hộp thoại. Đó là cách duy nhất để thực hiện nó sau khi bạn đóng hộp thoại. – ilomambo

+0

iLomambo Bạn đã thử một trong những đầu với gọi Runnable – Lion789

0

Khai báo trường 'câu trả lời' trong hoạt động của bạn và đặt giá trị cho nó. Các trường của một lớp được hiển thị cho các lớp bên trong, vì vậy bạn có thể làm điều đó.

+0

Có .. Tôi đã không đề cập đến nó, nhưng tôi cần phương pháp được độc lập của lớp nó được định nghĩa trong Không thể sử dụng biến lớp. Tôi sẽ cập nhật câu hỏi để làm cho nó rõ ràng hơn. – ilomambo

3

Những gì bạn có thể làm là tạo Trình nghe cho Hộp thoại cảnh báo của bạn để nghe hành động AlertDialogs bằng cách sử dụng Giao diện.

Tạo giao diện.

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; 

    } 
} 

Bây giờ, trong lớp học của bạn chỉ cần thực hiện các giao diện mà bạn tạo bằng implements MyInterface.DialogReturn

sau đó bạn có thể đặt Listener và làm cho nó làm việc như hiển thị dưới đây,

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 
    } 
} 
+0

Tôi giả sử đề xuất của bạn hoạt động. Nhưng, một cách phức tạp để đạt được một điều đơn giản là gì! Bạn không nghĩ sao? – ilomambo

+0

Ya đúng, nhưng điều này không phức tạp lắm nếu chúng ta hiểu nó một lần và làm cho nó hoạt động. –

+2

@ilomambo Chào mừng bạn đến với Android! Chào mừng bạn đến với Java cho vấn đề đó.

14

tôi đã đăng sự cố tương tự trong diễn đàn này, nhưng cuối cùng tôi nhận được câu trả lời của mình. vấn đề của tôi trong bài đăng đó là cách tạo lớp hộp thoại xác nhận riêng có thể truy cập vào lớp hoặc hoạt động khác, vì vậy với lớp hộp thoại xác nhận đó, chúng tôi không cần viết mã dài.

đây là câu trả lời của tôi.

Trước tiên, bạn phải tạo 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; 
    } 
} 

Và đây là ví dụ để gọi nó trong lớp khác

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


} 
+0

Có ai đã thử điều này, bất kỳ câu trả lời nào không? – Lion789

+0

@ Lion789 Hãy xem câu trả lời của tôi cho bình luận của bạn trong câu trả lời của riêng tôi Bài kiểm tra thực sự ở đây là: đặt một số mã vào phương thức 'onClick()' ** sau ** gọi 'doClick()' để kiểm tra phản hồi của người dùng đối với hộp thoại 'DialogHandler' và xem liệu mã thực thi đó có đợi hộp thoại đóng lại hay không Tôi nghĩ nó sẽ không. – ilomambo

+2

Tôi thích cách tiếp cận của bạn và nó đang chạy. đã kiểm tra nó – Nepster

0

Tôi cũng đã phải vật lộn để sử dụng một hộp thoại xác nhận chặn và cuối cùng tôi đã làm nó sử dụng một 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; 
     } 

    } 
} 
1

tôi thấy rằng việc sử dụng jDeferred giúp trong trường hợp bạn muốn đợi đầu vào.

Về cơ bản, nó tương đương với việc sử dụng giao diện, nhưng thay vào đó bạn tạo trình xử lý xong và không thành công. Chỉ cần một sự thay thế để xem xét:

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

Thực hiện:

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

} 
1

Với Andriod, nó không phải là một ý tưởng tốt để chặn thread chạy bằng cách chờ đợi cho người dùng để nói 'có' hoặc 'không' .

Để yêu cầu xác nhận, bạn có thể xác định phương thức nhận AsynTask. Phương thức thực thi tác vụ đó nếu người dùng nhấn nút xác nhận.

Ví dụ:

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

Bạn có thể gọi nó là từ hoạt động của bạn với:

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

YourTask lớp phải mở rộng AsyncTask

0

Tôi đã thử tất cả các giải pháp và dễ dàng hơn và sạch sẽ nhất là giải pháp đầu tiên với Runnable, theo ý kiến ​​của tôi. Nó hỗ trợ hộp thoại trên trình lắng nghe nút Cancel, OnBAckPressed() và onOptionsItemSelected().

Mã như được mô tả mặc dù gọi là ans_false.run(); khi nhấp vào BUTTON_POSITIVE và ans_true.run(); khi nhấp vào BUTTON_NEGATIVE.

Dưới đây là đoạn code tôi sử dụng để khắc phục vấn đề rằng:

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

}

Các vấn đề liên quan