Android:将对话框按钮与活动连接的正确方法是什么?

时间:2013-11-02 04:27:36

标签: android dialog

以下是我想做的事情:

1)在Activity内部显示一个对话框。我通过调用:

使用DialogFragmentFragmentManager
dialogFragment.show(fragmentManager, "edit_task_list");

2)Dialog内部我有自定义Button的布局。我想在单击按钮后执行某些操作,然后关闭对话框。

我应该如何连接所有东西?我看到两个选择:

1)onclick中的Button属性和Actvity内的方法。这是我最初的计划,但我不知道如何从Dialog获取Activity来解雇它。即使这不是正确的方法,怎么办呢?我想了解这是如何运作的。

2)在Dialog中创建DialogFragment时,在按钮上设置点击监听器。这需要我将一些上下文从Activity传递到DialogFragment,因此我希望避免它(并尽可能简化DialogFragment)。

我应该选择哪些选项?

4 个答案:

答案 0 :(得分: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!
     }
}

答案 1 :(得分:0)

所有Activity和Fragment类都有一个内置的回调方法,供您在启动另一个Activity,Fragment,Dialog或DialogFragment时使用。

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

由于您想从Activity启动Dialog,因此使用Dialog类比DialogFragment类更好。后者更适合从Fragment开始对话,因为它有两种方法可以回传到Fragment(get/set TargetFragment()

Dialog类具有getOwnerActivity()方法。这是使用其构造函数创建Dialog时使用的Activity。

在Dialog类的按钮上设置onClickListener。将结果传递回Activity:

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

您要在意图中添加要发送的其他信息。

答案 2 :(得分:0)

  

1)按钮中的onclick属性和Actvity内的方法。   这是我最初的计划,但我不知道如何从中获取Dialog   解雇它的活动。即使这不是正确的方法,怎么可能   这样做了吗?我想了解这是如何运作的。

基本上,您的活动必须记住/知道当前哪个对话框处于活动状态curDialog=dialogFragment;,然后在处理按钮onclick操作时,您将知道要关闭哪个对话框。但这确实不是一个好主意,因为基本上Button View会从您的DialogFragment“泄漏”到您的Activity,这会破坏对象封装。

  

2)在创建对话框时设置按钮上的单击侦听器   DialogFragment。这将要求我传递一些上下文   对DialogFragment的活动,所以我想避免它(并保持   DialogFragment尽可能简单。)

如上所述,您不需要向其传递任何上下文,特别是因为您可以通过调用getActivity()来获取活动。

解决方案取决于多个活动是否会使用此对话框:

  1. 由单个活动使用:@ Martin的解决方案可以正常使用
  2. 由多个Activity使用:可以使用抽象,只有用户的决定才会传递给侦听器。这是一个(修改过的)解决方案,我遇到了同样的问题:

    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();
    }
    }
    
  3. 要使用它,需要提供一些其他信息:

        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作为第一&第二个参数。

答案 3 :(得分:0)

应该避免关于xml中的onClick属性的第一点。因为如果您尊重屏幕旋转或具有多个对话框的设置等事件,那么以这种方式处理Dialog可能会非常痛苦。这在大多数情况下导致泄露的窗口错误,并且需要不必要的代码开销来避免这种情况。因为您必须跟踪实际显示的对话框。 为了能够以这种方式关闭对话框,您可以使用您在调用时设置的标记dialogFragment.show(fragmentManager, "edit_task_list");

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

正确的解决方案是使用接口作为DialogFragment和Activity之间通信的回调。这使得Dialog模块化和代码变得容易。以下是docs的示例。为此,您不需要上下文。您只需将界面传递给onAttach()回调中的对话框即可。它有一个Activity作为参数的引用,它调用了Dialog。

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

在Dialog中单击Button按钮并调用其中的dismiss(),Dialog可以自行解除。看看这个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
    }
});

在Dialog的onPause()中,将接口的引用设置为null。这样,您可以确保仅在显示对话框时才使用回调。

您的活动看起来像这样能够处理回调:

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

我不知道您的整体设置,但如果您使用AlertDialog,则单击按钮会在方法返回时自动关闭对话框。