我使用DialogFragments的一些事情:从列表中选择项目,输入文本。
将值(即字符串或列表中的项)返回给调用活动/片段的最佳方法是什么?
目前,我正在使调用活动实现驳回监听器,并给予DialogFragment对活动的引用。然后Dialog在activity中调用ondismiss方法,activity从DialogFragment对象中抓取结果。非常混乱,它不能在配置更改(方向更改),因为DialogFragment失去了对活动的引用。
谢谢你的帮助。
我使用DialogFragments的一些事情:从列表中选择项目,输入文本。
将值(即字符串或列表中的项)返回给调用活动/片段的最佳方法是什么?
目前,我正在使调用活动实现驳回监听器,并给予DialogFragment对活动的引用。然后Dialog在activity中调用ondismiss方法,activity从DialogFragment对象中抓取结果。非常混乱,它不能在配置更改(方向更改),因为DialogFragment失去了对活动的引用。
谢谢你的帮助。
当前回答
在我的例子中,我需要将参数传递给一个targetFragment。但我发现异常"碎片已激活"所以我在我的DialogFragment中声明了一个接口,这是parentFragment实现的。当parentFragment启动一个DialogFragment时,它将自己设置为TargetFragment。然后在DialogFragment中调用
((Interface)getTargetFragment()).onSomething(selectedListPosition);
其他回答
正如你在这里看到的,有一个非常简单的方法来做到这一点。
在你的DialogFragment中添加一个接口监听器:
public interface EditNameDialogListener {
void onFinishEditDialog(String inputText);
}
然后,添加对该监听器的引用:
private EditNameDialogListener listener;
这将被用来“激活”监听器方法,也用来检查父Activity/Fragment是否实现了这个接口(见下文)。
在“调用”DialogFragment的Activity/FragmentActivity/Fragment中简单地实现了这个接口。
在你的DialogFragment中,你需要在你想要解散DialogFragment并返回结果的地方添加以下内容:
listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();
mEditText.getText(). tostring()将被传递回调用Activity。
注意,如果您想返回其他内容,只需更改侦听器所接受的参数。
最后,你应该检查接口是否由父活动/片段实际实现:
@Override
public void onAttach(Context context) {
super.onAttach(context);
// Verify that the host activity implements the callback interface
try {
// Instantiate the EditNameDialogListener so we can send events to the host
listener = (EditNameDialogListener) context;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(context.toString()
+ " must implement EditNameDialogListener");
}
}
这种技术非常灵活,即使你还不想结束对话框,也可以回调结果。
我很惊讶地看到,没有人建议使用本地广播进行DialogFragment到Activity的通信!我发现它比其他建议更简单、更清晰。本质上,您为您的Activity注册侦听广播,并从您的DialogFragment实例发送本地广播。简单。有关如何设置它的一步一步的指南,请参见这里。
如果你想发送参数并从第二个片段接收结果,你可以使用fragment。setargarguments来完成这个任务
static class FirstFragment extends Fragment {
final Handler mUIHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 101: // receive the result from SecondFragment
Object result = msg.obj;
// do something according to the result
break;
}
};
};
void onStartSecondFragments() {
Message msg = Message.obtain(mUIHandler, 101, 102, 103, new Object()); // replace Object with a Parcelable if you want to across Save/Restore
// instance
putParcelable(new SecondFragment(), msg).show(getFragmentManager().beginTransaction(), null);
}
}
static class SecondFragment extends DialogFragment {
Message mMsg; // arguments from the caller/FirstFragment
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
mMsg = getParcelable(this);
}
void onClickOK() {
mMsg.obj = new Object(); // send the result to the caller/FirstFragment
mMsg.sendToTarget();
}
}
static <T extends Fragment> T putParcelable(T f, Parcelable arg) {
if (f.getArguments() == null) {
f.setArguments(new Bundle());
}
f.getArguments().putParcelable("extra_args", arg);
return f;
}
static <T extends Parcelable> T getParcelable(Fragment f) {
return f.getArguments().getParcelable("extra_args");
}
在我的例子中,我需要将参数传递给一个targetFragment。但我发现异常"碎片已激活"所以我在我的DialogFragment中声明了一个接口,这是parentFragment实现的。当parentFragment启动一个DialogFragment时,它将自己设置为TargetFragment。然后在DialogFragment中调用
((Interface)getTargetFragment()).onSomething(selectedListPosition);
只是把它作为一个选项(因为还没有人提到它)——你可以使用像Otto这样的事件总线。 所以在对话中你要这样做:
bus.post(new AnswerAvailableEvent(42));
并让你的调用者(Activity或Fragment)订阅它:
@Subscribe public void answerAvailable(AnswerAvailableEvent event) {
// TODO: React to the event somehow!
}