从DialogFragment接收结果
我正在使用DialogFragments的许多事情:从列表中select项目,input文本。
什么是最好的方式返回一个值(即从列表中的string或项目)回到调用活动/片段?
目前,我正在使调用活动实现DismissListener
并给DialogFragment一个参考活动。 然后Dialog调用活动中的OnDimiss
方法,活动从DialogFragment对象中获取结果。 非常混乱,而且在DialogFragment失去对活动的引用时,它不能在configuration更改(方向更改)上工作。
谢谢你的帮助。
从显示对话框的位置使用myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE)
,然后当对话结束时,可以调用getTargetFragment().onActivityResult(getTargetRequestCode(), ...)
,并实现onActivityResult()
在包含片段中。
这似乎是onActivityResult()
的滥用,尤其是因为它根本不涉及任何活动。 但是我已经看到官方的谷歌推荐,甚至可能在API的演示。 我想这是什么g/setTargetFragment()
被添加。
正如你在这里看到的,有一个非常简单的方法来做到这一点。
在你的DialogFragment
添加一个接口监听器,如:
public interface EditNameDialogListener { void onFinishEditDialog(String inputText); }
然后,添加对该侦听器的引用:
private EditNameDialogListener listener;
这将用于“激活”侦听器方法,还用于检查父Activity / Fragment是否实现了此接口(请参见下文)。
在“调用” DialogFragment
的Activity
/ FragmentActivity
/ Fragment
中简单地实现这个接口。
在你的DialogFragment
你需要添加一个你想closuresDialogFragment
并返回结果是这样的:
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,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(一旦Dialogclosures就调用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);
设置一个目标Fragment
而不是Activity
。 所以为了做到这一点,你需要使用一个InterfaceCommunicator
实现。
在你的DialogFragment
设置一个全局variables
public InterfaceCommunicator interfaceCommunicator;
创build一个公共的函数来处理它
public interface InterfaceCommunicator { void sendRequestCode(int code); }
然后,当您准备好在DialogFragment
运行DialogFragment
代码发送回Activity
时,您只需在dismiss();
之前添加该行即可dismiss();
你的DialogFragment
:
interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.
在你的活动中,你必须做两件事,第一件是删除不再适用的那一行代码:
dialogFrag.setTargetFragment(this, 1);
然后实现界面,你都完成了。 您可以通过将以下行添加到类的最顶部的implements
子句中来implements
:
public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator
然后@Override
活动中的function,
@Override public void sendRequestCode(int code) { // your code here }
您可以像使用onActivityResult()
方法一样使用此接口方法。 除了接口方法是用于DialogFragments
,另一个用于Fragments
。
那么为时已晚,可能会回答,但这是我从DialogFragment
得到的结果。 非常类似@布兰登的答案。 在这里,我从一个片段调用DialogFragment
,只需将这个代码放在你调用对话框的地方。
FragmentManager fragmentManager = getFragmentManager(); categoryDialog.setTargetFragment(this,1); categoryDialog.show(fragmentManager, "dialog");
其中categoryDialog
是我想要调用的DialogFragment
,然后在实现dialogfragment
,将此代码放置在您正在设置数据的位置。 resultCode
的值是1,您可以设置它或使用系统Defined。
Intent intent = new Intent(); intent.putExtra("listdata", stringData); getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent); getDialog().dismiss();
现在是回到调用片段并实现这个方法的时候了。 检查数据有效性或结果是否成功,如果你想resultCode
和requestCode
在if条件。
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //do what ever you want here, and get the result from intent like below String myData = data.getStringExtra("listdata"); Toast.makeText(getActivity(),data.getStringExtra("listdata"),Toast.LENGTH_SHORT).show(); }
我很惊讶地看到,没有人build议使用本地广播进行DialogFragment
到Activity
通信! 我发现它比其他build议更简单,更清洁。 基本上,你注册你的Activity
来监听广播,并从DialogFragment
实例发送本地广播。 简单。 有关如何完成设置的分步指南,请参阅此处 。
我发现一个简单的方法是:实现这是你的dialogFragment,
CallingActivity callingActivity = (CallingActivity) getActivity(); callingActivity.onUserSelectValue("insert selected value here"); dismiss();
然后在调用Dialog Fragment的活动中创build相应的function:
public void onUserSelectValue(String selectedValue) { // TODO add your implementation. Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show(); }
敬酒是要表明它的工作。 为我工作。
不同的方法,以允许一个片段沟通到其活动 :
1)在片段中定义一个公共接口并为其创build一个variables
public OnFragmentInteractionListener mCallback; public interface OnFragmentInteractionListener { void onFragmentInteraction(int id); }
2)将活动投射到片段中的mCallbackvariables
try { mCallback = (OnFragmentInteractionListener) getActivity(); } catch (Exception e) { Log.d(TAG, e.getMessage()); }
3)在你的活动中实现听众
public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener { //your code here }
4)覆盖活动中的OnFragmentInteraction
@Override public void onFragmentInteraction(int id) { Log.d(TAG, "received from fragment: " + id); }
更多信息: https : //developer.android.com/training/basics/fragments/communicating.html
在我的情况下,我需要传递参数到一个targetFragment。 但是我得到了“片段已经激活”的例外。 所以我在DialogFragment中声明了一个实现了parentFragment的接口。 当parentFragment启动一个DialogFragment时,它将自己设置为TargetFragment。 然后在DialogFragment中调用
((Interface)getTargetFragment()).onSomething(selectedListPosition);
只是把它作为选项之一(因为没有人提到它) – 你可以使用像奥托这样的事件公共汽车。 所以在对话框中你可以:
bus.post(new AnswerAvailableEvent(42));
并让你的调用者(Activity或Fragment)订阅它:
@Subscribe public void answerAvailable(AnswerAvailableEvent event) { // TODO: React to the event somehow! }