2013-11-02 42 views
0

以下是我想要做的:Android:將對話按鈕與活動連接的正確方式是什麼?

1)在Activity內部會顯示一個對話框。我用DialogFragmentFragmentManager爲此,通過調用:

dialogFragment.show(fragmentManager, "edit_task_list"); 

2)Dialog裏面我有佈局,自定義Button。我想在點擊按鈕時執行一些操作,然後關閉對話框。

我該如何連接一切?我看到兩個選項:

1)onclickButton屬性和Actvity內的方法。這是我原來的計劃,但我不知道如何從Activity中得到Dialog來解僱它。即使這不是正確的方式,這怎麼可能呢?我想了解這是如何工作的。

2)在DialogFragment中創建Dialog時,在按鈕上設置點擊監聽器。這將需要我將Activity的某些上下文傳遞給DialogFragment,所以我想避免它(並儘可能簡化DialogFragment)。

我應該選擇哪些選項?

+0

我想你應該使用接口和活動來實現它的方法。你可以傳遞所有有用的對象,甚至是對話對象。 – Aleksandr

回答

0

Number 2不需要你傳遞任何上下文(你不應該)。您定義了一個接口,可以充當碎片和活動之間的契約,並讓您的活動實施它。

從您的對話框,並在你的button.onClick(),你做這樣的事情(未測試的代碼):

if (getActivity() != null 
     && !getActivity().finishing() 
     && getActivity() instanceOf YourInterface) { 
    ((YourInterface)getActivity()).onSomeNiceMethod(); 
    dismiss(); // close the dialog (if this is what you want). 
} 

接口看起來像:

public interface YourInterface { 
    void onSomeNiceMethod(); 
} 

而且你的活動......

public class YourActivity implements YourInterface { 
    void onSomeNiceMethod() { 
     // Hey! The Button In The Dialog Has Been Pressed! 
    } 
} 
0

所有Activity和Fragment類都有一個內置的回調方法供您在啓動時使用另一個Activity,Fragment,Dialog或DialogFragment。

void onActivityResult(int requestCode, int resultCode, Intent data) 

由於您想從Activity啓動對話框,因此使用Dialog類比DialogFragment類更好。後者更適合從片段開始對話,因爲它有兩種方法可用於傳回片段(get/set TargetFragment()

對話框類具有getOwnerActivity()方法。這是您在使用其構造函數之一創建對話框時使用的Activity。

您在Dialog類的按鈕上設置了onClickListener。將結果傳遞迴活動:

getOwnerActivity().onActivityResult(intIdentifyingme, Activity.RESULT_OK, 
        intent); 
dismiss(); // close the dialog 

您將其他信息發送給意圖。

0

1)Button中的onclick屬性和Actvity中的方法。 這是我的原始計劃,但我不知道如何從 活動中獲得對話以解除它。即使這不是正確的方法,那麼 這個可以完成嗎?我想了解這是如何工作的。

基本上你的活動必須記住/知道哪個對話框是活動的東西,如curDialog=dialogFragment;了一會兒,然後處理按鈕的onclick行動,你就會知道解僱哪個對話框時。但這真的不是一個好主意,因爲基本上Button View會從DialogFragment「泄漏」到您的Activity中,這會破壞對象封裝。

2)當在DialogFragment中創建對話框時在按鈕上設置點擊監聽器。這將需要我將 Activity的一些上下文傳遞給DialogFragment,所以我想避免它(並儘可能簡化DialogFragment的設置)。

作爲前面提到的答案,您不需要傳遞任何上下文,特別是因爲您可以通過調用getActivity()來獲取活動。

的解決方案取決於是否該對話框會由多個活動中使用:

  1. 由單一的活動中使用:@馬丁的解決方案將工作得很好
  2. 由多個活動中使用:抽象可以被用來使得只有用戶的決定被傳遞給聽衆。這是一個(修改)的解決方案,我想出了爲同樣的問題:

    public class BaseDialogFragment extends DialogFragment { 
        protected TextView dialogEn; 
        protected Button dialogYes; 
        private Button dialogNo; 
        protected OnSelectListener listener; 
    
    public interface OnSelectListener { 
        public void onSelect(int type, boolean yes); 
    } 
    
    public void setOnSelectListener(OnSelectListener listener) { 
        this.listener = listener; 
    } 
    
    public BaseDialogFragment() { 
        super(); 
    } 
    
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.dialog_confirm, container, false); 
    dialogYes = (Button) v.findViewById(R.id.yes); 
    dialogNo = (Button) v.findViewById(R.id.no); 
    
    dialogEn = (TextView) view.findViewById(R.id.dialog_en); 
    dialogEn.setText(getArguments().getString("text_en")); 
    dialogYes.setOnClickListener(this); 
    dialogNo.setOnClickListener(this); 
    return v; 
    } 
    
    public void onClick(View v) { 
        if (listener != null) { 
         listener.onSelect(getArguments().getInt("type"), 
           v == dialogYes ? true : false); 
        } 
        getDialog().dismiss(); 
    } 
    } 
    

要使用一些額外的信息需要提供:

Bundle bundle = new Bundle(); 
    bundle.putInt("type", type); //type: an unique integer value that helps differentiate result from different dialogs 
    bundle.putString("text_en", en); //en: String to be displayed 
    dialog.setArguments(bundle); 
    dialog.setOnSelectListener(this); 

因此,如果type值以上設置爲115,那麼點擊按鈕dialogYes將觸發public void onSelect(int type, boolean yes)方法以115true作爲第一參數&。

0

你應該避免在xml中關於onClick屬性的第一點。因爲如果您尊重屏幕旋轉等事件或使用多個對話框進行設置,那麼以這種方式處理對話框可能會非常痛苦。這導致大多數時間泄露的窗口錯誤,並且需要不必要的代碼開銷來避免這種情況。因爲你必須跟蹤自己實際顯示的對話框。 爲了能夠關閉對話框。這種方式,您可以使用您設置好的標籤,你叫dialogFragment.show(fragmentManager, "edit_task_list");

DialogFragment frag = (DialogFragment)getFragmentManager().findFragmentByTag("edit_task_list"); 
if(frag != null) 
    frag.dismiss(); 

正確的解決方案是使用一個接口作爲DialogFragment和活動之間的通信的回調。這使Dialog模塊化和代碼簡單。這是docs的一個例子。爲此,你不需要一個上下文。您只需將界面傳遞給onAttach()回調中的對話框即可。它有一個Activity作爲參數的參考,該參數調用該對話框。

// Example interface for the communication 
public interface OnArticleSelectedListener { 
    public void onButtonClicked(/*any Parameters*/); 
} 

public static class FragmentA extends DialogFragment { 
    OnArticleSelectedListener mListener; 
    ... 
    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     try { 
      mListener = (OnArticleSelectedListener) activity; // get the interface of the Activity 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
        + " must implement OnArticleSelectedListener"); 
     } 
    } 
    ... 
} 

處理按鈕單擊對話框中並調用dismiss(),該對話框可以解除其自身。看看這個question爲什麼要用dismiss()代替getDialog()。dismiss()。

yourButton.setOnClickListener(new OnClickListener(){ 
    @Override 
    public void onClick(View v){ 
     if(mListener != null) // check if the listener is still valid 
      mListener.onButtonClicked(...); // calls the Activity implementation of this callback 
     dismiss(); // dismiss the Dialog 
    } 
}); 

在對話框的onPause()中,將接口的引用設置爲null。這樣,您可以確定只有在顯示對話框時纔會使用回調。

你的活動看起來是這樣的,以便能夠處理回調:

public class MyActivity extends Activity implements OnArticleSelectedListener{ 
    ... 
    @Override 
    public void onButtonClicked(...){ 
     // your implementation here 
    } 
} 

我不知道你的整體設置,但如果你使用一個AlertDialog一個點擊按鈕時自動關閉對話框。該方法返回。

相關問題