2013-02-09 25 views
19

Tôi có một đơn giản AlertDialog hiển thị danh sách một số mục và sau khi nhấp vào một trong số chúng, mục được nhấp sẽ được chuyển trở lại kèm theo Activity. Tôi cũng muốn thực hiện một số xử lý mặc định khi người dùng hủy hộp thoại (bằng cách sử dụng nút quay lại ) - cụ thể hơn, tôi muốn chuyển một chuỗi trống đến hoạt động trong trường hợp này.OnCancelListener không được gọi trong Hộp thoại

Tuy nhiên, nếu tôi đặt hộp thoại trong một DialogFragment (từ gói tương thích), các OnCancelListenerkhông được gọi khi tôi đóng hộp thoại với nút quay lại. Tôi đang làm gì sai?

public class SelectItemDialog extends DialogFragment { 

    public interface Callback { 
     void onItemSelected(String string); 
    } 

    private static final String ARG_ITEMS = "items"; 

    private Callback callback; 

    public static SelectItemDialog fromItems(Collection<String> items) { 
     SelectItemDialog fragment = new SelectItemDialog(); 
     fragment.setArguments(newArguments(items)); 
     return fragment; 
    } 

    private static Bundle newArguments(Collection<String> items) { 
     Bundle arguments = new Bundle(); 
     arguments.putStringArray(ARG_ITEMS, items.toArray(new String[items.size()])); 
     return arguments; 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     callback = (Callback) activity; 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     final String[] items = getArguments().getStringArray(ARG_ITEMS); 
     return new AlertDialog.Builder(getActivity()) 
      .setTitle(R.string.dialog_select_email_title) 
      .setItems(items, new OnClickListener() { 
       @Override 
       public void onClick(DialogInterface dialog, int which) { 
        callback.onItemSelected(items[which]); 
       } 
      }) 
      .setOnCancelListener(new OnCancelListener() { 
       @Override 
       public void onCancel(DialogInterface dialog) { 
        // this code is not executed 
        callback.onItemSelected(""); 
        throw new RuntimeException("dialog cancelled"); 
       } 
      }) 
      .create(); 
    } 
} 

Trả lời

42

Có thể phải thực hiện với thực tế là không có lệnh gọi rõ ràng nào đến số cancel() từ mã của bạn. Các tài liệu OnCancelListener nói:

này sẽ chỉ được gọi khi hộp thoại bị hủy

Mà có lẽ cần một rõ ràng cancel() gọi.

Hoặc thực hiện nút tích cực/tiêu cực với số OnClickListener gọi DialogInterface#cancel() hoặc sử dụng OnDismissListener() với một kiểm tra bổ sung để xem liệu mục danh sách đã được nhấp hay chưa.

Ngoài ra, để lắng nghe một phím nhấn trở lại và hủy bỏ hộp thoại, bạn có thể thiết lập một OnKeyListener, như được nêu trong this SO answer

Ngoài ra, một khi bạn có Dialog thiết lập, nó cũng sẽ là một ý tưởng tốt để sử dụng Dialog#setCanceledOnTouchOutside() trong trường hợp người dùng nhấn bên ngoài Hộp thoại.

Chỉnh sửa: Phần dưới đây là cách dễ dàng để xử lý các sự kiện hủy trong DialogFragment.

Vì bạn đang sử dụng một DialogFragment, lớp này có một phương pháp rất tiện dụng, DialogFragment#onCancel() mà được gọi khi DialogFragment bị hủy. Làm logic của bạn trong đó.

DialogFragments phức tạp hơn, với vòng đời hơi khác so với hộp thoại thông thường. Do đó, trước tiên hãy kiểm tra tài liệu nếu bạn có phương thức dựa trên Dialog nhất định mà bạn đang cố gắng chuyển đến DialogFragment, một số phương pháp có thể tồn tại cho phép triển khai mới của bạn hoạt động bình thường!

+1

tôi thay đổi nội dung câu hỏi của tôi. Tôi muốn mã trong 'OnCancelListener' được gọi khi hộp thoại được đóng lại với nút * quay lại *. – Natix

+0

@Natix xem [câu trả lời này] (http://stackoverflow.com/a/7815342/1815485), nó đang làm điều tương tự. Bạn phải thêm một 'OnKeyListener' để xem cho việc bấm phím trở lại. –

+0

Vâng, giải pháp này có thể hoạt động, nhưng nếu tôi tạo hộp thoại trực tiếp bên trong một hoạt động mà không có 'DialogFragment', thì 'OnCancelListener' được gọi - cả khi nút quay lại được nhấn hoặc nếu người dùng nhấp vào bên ngoài hộp thoại. Tôi không hiểu tại sao 'DialogFragment' thay đổi hành vi. – Natix

11

Nếu bạn đang sử dụng DialogFragment và muốn nghe lại nút sau đó sử dụng này -

this.getDialog().setOnKeyListener(new Dialog.OnKeyListener() { 
     @Override 
     public boolean onKey(DialogInterface dialog, int keyCode, 
       KeyEvent event) { 
      if (keyCode == KeyEvent.KEYCODE_BACK) { 
       if (****) { 
        your logic 
       } 
       return true; 
      } 
      return false; 
     } 
    }); 
+0

Cảm ơn bạn đã thực sự trả lời câu hỏi! đó là phần getDialog đã ném tôi đi! –

1

Trên thực tế nếu bạn muốn sử dụng DialogFragment, bạn không bao giờ có thể thêm OnCancelListener hoặc OnDismissListener đến nó, kể từ khi Dialog Fragment sở hữu callbacks cho các phương pháp này!

Bạn có 3 tùy chọn tại đây:

1- đi với hộp thoại thông thường.
2- đặt đoạn hộp thoại của bạn thành hủy (false) và thêm nút hủy vào hộp thoại.
3 kiểm tra câu trả lời @Nikhil Pingle.

này là từ các tài liệu của Dialog Fragment

* <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener 
* Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener 
* Dialog.setOnDismissListener} callbacks. You must not set them yourself.</em> 
* To find out about these events, override {@link #onCancel(DialogInterface)} 
* and {@link #onDismiss(DialogInterface)}.</p> 
-1

Hủy Listener hoặc Bỏ người nghe trong DialogFragment có thể đạt được bằng cách onDismiss

  DialogFragment newFragment = new DatePickerFragment(); 
      newFragment.show(getFragmentManager(), "datePicker"); 
      newFragment.onDismiss(new DialogInterface(){ 

       @Override 
       public void cancel() { 
        // TODO Auto-generated method stub 

       } 

       @Override 
       public void dismiss() { 
        // TODO Auto-generated method stub 

       } 

      }); 
+0

Mã này thực sự sẽ làm cho hộp thoại được hiển thị và bị loại bỏ ngay lập tức vì lệnh gọi 'DialogFragment.onDismiss (...)'. Người dùng thậm chí sẽ không nhìn thấy nó. –

7

Lưu ý: DialogFragment sở hữu Dialog.setOnCancelListener và Dialog. setOnDismissListener callbacks. Bạn không được tự đặt chúng.

Để tìm hiểu về các sự kiện này, hãy ghi đè lênCancel (DialogInterface) và onDismiss (DialogInterface).

public class SelectItemDialog extends DialogFragment { 

    @Override 
    public void onDismiss(DialogInterface dialog) { 
     super.onDismiss(dialog); 
     //your code hear 
     dialog.cancel(); 
    } 
} 

Và bạn nên loại bỏ .setOnCancelListener()

+0

cảm ơn rất nhiều, rõ ràng là con đường để đi – noloman

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