2013-02-09 51 views
19

我有一個簡單的AlertDialog,它顯示了一些項目的列表,並且在單擊其中一個項目後,被單擊的項目被傳回到封閉的Activity。我也想在用戶取消對話時執行一些默認處理(使用後退按鈕) - 更具體地說,我想在這種情況下將空字符串傳遞給活動。OnCancelListener未在DialogFragment中調用

但是,如果我把在對話框中DialogFragment(從兼容包),該OnCancelListener沒有當我關閉對話框,返回按鈕調用。我究竟做錯了什麼?

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

回答

42

這可能與事實,那就是從你的代碼cancel()沒有明確的調用來完成。 的OnCancelListener文件說:當對話框被取消

這可能需要一個明確的cancel()呼叫

這隻會被調用。

要麼做一個正/負鍵與OnClickListener調用DialogInterface#cancel()或使用OnDismissListener()一個額外的檢查,看是否被點擊列表項。

而且,聽一回按鍵和取消對話框,你可以建立一個OnKeyListener,像this SO answer

概述此外,一旦你的對話框中設置了,這也將是一個不錯的主意如果用戶在對話外部輕擊,則使用Dialog#setCanceledOnTouchOutside()

編輯:下面的部分是在DialogFragment中處理取消事件的簡單方法。

由於您使用的是DialogFragment,這個類有一個非常方便的方法,DialogFragment#onCancel()DialogFragment取消其被調用。在那裏做你的邏輯。

DialogFragments比較複雜,與普通對話框的生命週期略有不同。因此,如果您有一個基於Dialog的方法試圖移植到DialogFragment,那麼首先檢查文檔,可能存在一些方法可以讓您的新實現正常工作!

+1

我編輯我的問題。我希望在用「後退」按鈕*關閉對話框時調用「OnCancelListener」中的代碼。 – Natix 2013-02-09 16:40:18

+0

@Natix看到[這個答案](http://stackoverflow.com/a/7815342/1815485),它是做同樣的事情。你必須添加一個'OnKeyListener'來監視後退按鍵。 – 2013-02-09 16:42:19

+0

嗯,這個解決方案應該可能工作,但如果我直接在沒有'DialogFragment'的活動內部創建對話框,那麼'OnCancelListener'被調用 - 無論是當後退按鈕被按下時,還是用戶在對話框外單擊。我不明白爲什麼'DialogFragment'改變了行爲。 – Natix 2013-02-09 16:59:50

11

如果您正在使用DialogFragment,想聽聽後退按鈕,然後使用此 - 如果你想使用DialogFragment

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

感謝您回答問題!這是getDialog部分扔了我! – 2014-02-26 14:59:57

1

其實,你永遠無法添加OnCancelListenerOnDismissListener它,因爲對話片段擁有這些方法的回調!

你有3個選擇這裏:

1-去定期對話。
2-將對話框片段設置爲可取消(false),並向對話框中添加取消按鈕。
3-檢查@Nikhil Pingle的答案。

這是從的對話片段

* <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

文檔取消監聽器或駁回DialogFragment聽衆可以通過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

由於DialogFragment.onDismiss(...)調用,此代碼實際上會導致顯示對話框並立即取消對話。用戶甚至不會看到它。 – 2014-11-05 11:22:11

7

注意做到:DialogFragment擁有Dialog.setOnCancelListener和對話。 setOnDismissListener回調。你不能自己設置它們。

要了解這些事件,請覆蓋onCancel(DialogInterface)和onDismiss(DialogInterface)。

public class SelectItemDialog extends DialogFragment { 

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

而且你應該刪除.setOnCancelListener()

+0

非常感謝,明確的路要走 – noloman 2016-02-09 13:37:19

相關問題