我使用DialogFragments的一些事情:从列表中选择项目,输入文本。
将值(即字符串或列表中的项)返回给调用活动/片段的最佳方法是什么?
目前,我正在使调用活动实现驳回监听器,并给予DialogFragment对活动的引用。然后Dialog在activity中调用ondismiss方法,activity从DialogFragment对象中抓取结果。非常混乱,它不能在配置更改(方向更改),因为DialogFragment失去了对活动的引用。
谢谢你的帮助。
我使用DialogFragments的一些事情:从列表中选择项目,输入文本。
将值(即字符串或列表中的项)返回给调用活动/片段的最佳方法是什么?
目前,我正在使调用活动实现驳回监听器,并给予DialogFragment对活动的引用。然后Dialog在activity中调用ondismiss方法,activity从DialogFragment对象中抓取结果。非常混乱,它不能在配置更改(方向更改),因为DialogFragment失去了对活动的引用。
谢谢你的帮助。
当前回答
在Kotlin
// My DialogFragment
class FiltroDialogFragment : DialogFragment(), View.OnClickListener {
var listener: InterfaceCommunicator? = null
override fun onAttach(context: Context?) {
super.onAttach(context)
listener = context as InterfaceCommunicator
}
interface InterfaceCommunicator {
fun sendRequest(value: String)
}
override fun onClick(v: View) {
when (v.id) {
R.id.buttonOk -> {
//You can change value
listener?.sendRequest('send data')
dismiss()
}
}
}
}
//我的活动
class MyActivity: AppCompatActivity(),FiltroDialogFragment.InterfaceCommunicator {
override fun sendRequest(value: String) {
// :)
Toast.makeText(this, value, Toast.LENGTH_LONG).show()
}
}
我希望它服务,如果你可以改进,请编辑它。 我的英语不太好
其他回答
我很惊讶地看到,没有人建议使用本地广播进行DialogFragment到Activity的通信!我发现它比其他建议更简单、更清晰。本质上,您为您的Activity注册侦听广播,并从您的DialogFragment实例发送本地广播。简单。有关如何设置它的一步一步的指南,请参见这里。
有一种更简单的方法来接收来自DialogFragment的结果。
首先,在你的Activity、Fragment或FragmentActivity中,你需要添加以下信息:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Stuff to do, dependent on requestCode and resultCode
if(requestCode == 1) { // 1 is an arbitrary number, can be any int
// This is the return result of your DialogFragment
if(resultCode == 1) { // 1 is an arbitrary number, can be any int
// Now do what you need to do after the dialog dismisses.
}
}
}
requestCode基本上是你调用的DialogFragment的int标签,我马上会展示它是如何工作的。resultCode是你从DialogFragment发送回来的代码,告诉你当前正在等待的Activity、Fragment或FragmentActivity发生了什么。
下一段代码是对DialogFragment的调用。这里有一个例子:
DialogFragment dialogFrag = new MyDialogFragment();
// This is the requestCode that you are sending.
dialogFrag.setTargetFragment(this, 1);
// This is the tag, "dialog" being sent.
dialogFrag.show(getFragmentManager(), "dialog");
用这三行你声明了你的DialogFragment,设置了一个requestCode(它将调用onActivityResult(…)一旦对话框被驳回,然后你就会显示对话框。就是这么简单。
现在,在你的DialogFragment中,你只需要在dismiss()之前直接添加一行,这样你就可以将resultCode发送回onActivityResult()。
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent());
dismiss();
就是这样。注意,resultCode被定义为int resultCode,我已经设置为resultCode = 1;在这种情况下。
就是这样,你现在可以把你的DialogFragment的结果发送回你调用的Activity, Fragment,或者FragmentActivity。
另外,看起来这些信息之前已经发布了,但是没有给出足够的例子,所以我想我应该提供更多的细节。
编辑06.24.2016 我为上面的误导性代码道歉。但是你肯定不能接收回活动的结果,就像这行:
dialogFrag.setTargetFragment(this, 1);
设置目标片段而不是活动。为了做到这一点,你需要实现一个interfacecommunator。
在你的DialogFragment中设置一个全局变量
public InterfaceCommunicator interfaceCommunicator;
创建一个公共函数来处理它
public interface InterfaceCommunicator {
void sendRequestCode(int code);
}
然后,当你准备好在DialogFragment完成运行时将代码发送回Activity时,你只需在你dismiss()之前添加一行;你的DialogFragment:
interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.
现在在你的活动中你必须做两件事,第一件事是删除那一行不再适用的代码:
dialogFrag.setTargetFragment(this, 1);
然后实现接口,一切都完成了。你可以通过在类顶部的implements子句中添加以下一行来做到这一点:
public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator
然后@Override activity中的函数,
@Override
public void sendRequestCode(int code) {
// your code here
}
使用这个接口方法就像使用onActivityResult()方法一样。除了接口方法是针对DialogFragments,另一个是针对Fragments。
对于还在阅读这篇文章的人:setTargetFragment()已被弃用。现在建议像这样使用FragmentResultListener API:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setFragmentResultListener("requestKey") { key, bundle ->
val result = bundle.getString("resultKey")
// Do something with the result...
}
...
// Somewhere show your dialog
MyDialogFragment.newInstance().show(parentFragmentManager, "tag")
}
然后在你的MyDialogFragment中设置结果:
button.setOnClickListener{
val result = "some string"
setFragmentResult("requestKey", bundleOf("resultKey" to result))
dismiss()
}
在Kotlin
// My DialogFragment
class FiltroDialogFragment : DialogFragment(), View.OnClickListener {
var listener: InterfaceCommunicator? = null
override fun onAttach(context: Context?) {
super.onAttach(context)
listener = context as InterfaceCommunicator
}
interface InterfaceCommunicator {
fun sendRequest(value: String)
}
override fun onClick(v: View) {
when (v.id) {
R.id.buttonOk -> {
//You can change value
listener?.sendRequest('send data')
dismiss()
}
}
}
}
//我的活动
class MyActivity: AppCompatActivity(),FiltroDialogFragment.InterfaceCommunicator {
override fun sendRequest(value: String) {
// :)
Toast.makeText(this, value, Toast.LENGTH_LONG).show()
}
}
我希望它服务,如果你可以改进,请编辑它。 我的英语不太好
如果你想发送参数并从第二个片段接收结果,你可以使用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");
}