Android 从 DialogFragment 接收结果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10905312/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Receive result from DialogFragment
提问by James Cross
I am using DialogFragmentsfor a number of things: choosing item from list, entering text.
我将DialogFragments用于许多事情:从列表中选择项目,输入文本。
What is the best way to return a value (i.e. a string or an item from a list) back to the calling activity/fragment?
将值(即字符串或列表中的项目)返回给调用活动/片段的最佳方法是什么?
Currently I am making the calling activity implement DismissListener
and giving the DialogFragment a reference to the activity. The Dialog then calls the OnDimiss
method in the activity and the activity grabs the result from the DialogFragment object. Very messy and it doesn't work on configuration change (orientation change) as the DialogFragment loses the reference to the activity.
目前,我正在实现调用活动DismissListener
并为 DialogFragment 提供对活动的引用。然后 Dialog 调用OnDimiss
活动中的方法,活动从 DialogFragment 对象中获取结果。非常混乱,它不适用于配置更改(方向更改),因为 DialogFragment 丢失了对活动的引用。
Thanks for any help.
谢谢你的帮助。
回答by Timmmm
Use myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE)
from the place where you show the dialog, and then when your dialog is finished, from it you can call getTargetFragment().onActivityResult(getTargetRequestCode(), ...)
, and implement onActivityResult()
in the containing fragment.
myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE)
从显示对话框的地方开始使用,然后当您的对话框完成时,您可以从中调用getTargetFragment().onActivityResult(getTargetRequestCode(), ...)
,并onActivityResult()
在包含片段中实现。
It seems like an abuse of onActivityResult()
, especially as it doesn't involve activities at all. But I've seen it recommended by official google people, and maybe even in the api demos. I think it's what g/setTargetFragment()
were added for.
这似乎是对 的滥用onActivityResult()
,尤其是因为它根本不涉及活动。但我已经看到官方谷歌人推荐它,甚至可能在 api 演示中。我认为这g/setTargetFragment()
是添加的目的。
回答by Assaf Gamliel
As you can see herethere is a very simple way to do that.
In your DialogFragment
add an interface listener like:
在您DialogFragment
添加一个接口侦听器,如:
public interface EditNameDialogListener {
void onFinishEditDialog(String inputText);
}
Then, add a reference to that listener:
然后,添加对该侦听器的引用:
private EditNameDialogListener listener;
This will be used to "activate" the listener method(s), and also to check if the parent Activity/Fragment implements this interface (see below).
这将用于“激活”侦听器方法,并检查父 Activity/Fragment 是否实现了此接口(见下文)。
In the Activity
/FragmentActivity
/Fragment
that "called" the DialogFragment
simply implement this interface.
在Activity
/ FragmentActivity
/Fragment
说:“所谓的”DialogFragment
简单地实现这个接口。
In your DialogFragment
all you need to add at the point where you'd like to dismiss the DialogFragment
and return the result is this:
在您DialogFragment
需要添加的所有内容中,您要关闭DialogFragment
并返回结果是这样的:
listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();
Where mEditText.getText().toString()
is what will be passed back to the calling Activity
.
mEditText.getText().toString()
将传递回调用的内容在哪里Activity
。
Note that if you want to return something else simply change the arguments the listener takes.
请注意,如果您想返回其他内容,只需更改侦听器采用的参数即可。
Finally, you should check whether the interface was actually implemented by the parent activity/fragment:
最后,您应该检查该接口是否由父 Activity/Fragment 实际实现:
@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");
}
}
This technique is very flexible and allow calling back with the result even if your don;t want to dismiss the dialog just yet.
这种技术非常灵活,即使您还不想关闭对话框,也可以使用结果进行回调。
回答by Brandon
There is a much simpler way to receive a result from a DialogFragment.
有一种更简单的方法可以从 DialogFragment 接收结果。
First, in your Activity, Fragment, or FragmentActivity you need to add in the following information:
首先,在您的 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.
}
}
}
The requestCode
is basically your int label for the DialogFragment you called, I'll show how this works in a second. The resultCode is the code that you send back from the DialogFragment telling your current waiting Activity, Fragment, or FragmentActivity what happened.
这requestCode
基本上是您调用的 DialogFragment 的 int 标签,我将在稍后展示它是如何工作的。resultCode 是您从 DialogFragment 发回的代码,它告诉您当前等待的 Activity、Fragment 或 FragmentActivity 发生了什么。
The next piece of code to go in is the call to the DialogFragment. An example is here:
下一段代码是对 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");
With these three lines you are declaring your DialogFragment, setting a requestCode (which will call the onActivityResult(...) once the Dialog is dismissed, and you are then showing the dialog. It's that simple.
通过这三行,您可以声明 DialogFragment,设置 requestCode(一旦对话框被解除,它将调用 onActivityResult(...),然后您将显示对话框。就这么简单。
Now, in your DialogFragment you need to just add one line directly before the dismiss()
so that you send a resultCode back to the onActivityResult().
现在,在您的 DialogFragment 中,您只需在 之前直接添加一行,dismiss()
以便将 resultCode 发送回 onActivityResult()。
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent());
dismiss();
That's it. Note, the resultCode is defined as int resultCode
which I've set to resultCode = 1;
in this case.
就是这样。请注意, resultCode 被定义为int resultCode
我resultCode = 1;
在这种情况下设置的。
That's it, you can now send the result of your DialogFragment back to your calling Activity, Fragment, or FragmentActivity.
就是这样,您现在可以将 DialogFragment 的结果发送回您的调用 Activity、Fragment 或 FragmentActivity。
Also, it looks like this information was posted previously, but there wasn't a sufficient example given so I thought I'd provide more detail.
此外,看起来此信息之前已发布,但没有给出足够的示例,因此我想我会提供更多详细信息。
EDIT 06.24.2016I apologize for the misleading code above. But you most certainly cannot receive the result back to the activity seeing as the line:
编辑 06.24.2016我为上面的误导性代码道歉。但是您肯定无法将结果返回到活动中,如下所示:
dialogFrag.setTargetFragment(this, 1);
sets a target Fragment
and not Activity
. So in order to do this you need to use implement an InterfaceCommunicator
.
设定目标Fragment
而不是Activity
。所以为了做到这一点,你需要使用实现一个InterfaceCommunicator
.
In your DialogFragment
set a global variable
在你的DialogFragment
设置一个全局变量
public InterfaceCommunicator interfaceCommunicator;
Create a public function to handle it
创建一个公共函数来处理它
public interface InterfaceCommunicator {
void sendRequestCode(int code);
}
Then when you're ready to send the code back to the Activity
when the DialogFragment
is done running, you simply add the line before you dismiss();
your DialogFragment
:
然后,当你已经准备好发送代码回Activity
的时候DialogFragment
完成运行时,你只需在你面前添加行dismiss();
您DialogFragment
:
interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.
In your activity now you have to do two things, the first is to remove that one line of code that is no longer applicable:
现在在您的活动中,您必须做两件事,第一件事是删除不再适用的那一行代码:
dialogFrag.setTargetFragment(this, 1);
Then implement the interface and you're all done. You can do that by adding the following line to the implements
clause at the very top of your class:
然后实现接口就大功告成了。您可以通过implements
将以下行添加到班级最顶部的子句中来做到这一点:
public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator
And then @Override
the function in the activity,
然后@Override
是活动中的功能,
@Override
public void sendRequestCode(int code) {
// your code here
}
You use this interface method just like you would the onActivityResult()
method. Except the interface method is for DialogFragments
and the other is for Fragments
.
您可以像使用该方法一样使用此接口onActivityResult()
方法。除了接口方法是 for DialogFragments
,另一个是 for Fragments
。
回答by vikas kumar
Well its too late may be to answer but here is what i did to get results back from the DialogFragment
. very similar to @brandon's answer.
Here i am calling DialogFragment
from a fragment, just place this code where you are calling your dialog.
好吧,现在回答可能为时已晚,但这是我为从DialogFragment
. 与@brandon 的回答非常相似。在这里,我DialogFragment
从一个片段调用,只需将此代码放在您调用对话框的位置即可。
FragmentManager fragmentManager = getFragmentManager();
categoryDialog.setTargetFragment(this,1);
categoryDialog.show(fragmentManager, "dialog");
where categoryDialog
is my DialogFragment
which i want to call and after this in your implementation of dialogfragment
place this code where you are setting your data in intent. The value of resultCode
is 1 you can set it or use system Defined.
我想调用的categoryDialog
my在哪里DialogFragment
,然后在您执行dialogfragment
此代码的地方,您打算在其中设置数据。的值为resultCode
1,您可以设置它或使用系统定义。
Intent intent = new Intent();
intent.putExtra("listdata", stringData);
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
getDialog().dismiss();
now its time to get back to to the calling fragment and implement this method. check for data validity or result success if you want with resultCode
and requestCode
in if condition.
现在是时候回到调用片段并实现这个方法了。检查数据的有效性,或者如果你想成功的结果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();
}
回答by lcompare
Different approach, to allow a Fragmentto communicate up to its Activity:
不同的方法,允许Fragment与其Activity进行通信:
1)Define a public interface in the fragment and create a variable for it
1)在fragment中定义一个公共接口并为其创建一个变量
public OnFragmentInteractionListener mCallback;
public interface OnFragmentInteractionListener {
void onFragmentInteraction(int id);
}
2)Cast the activity to the mCallback variable in the fragment
2)将活动投射到片段中的 mCallback 变量
try {
mCallback = (OnFragmentInteractionListener) getActivity();
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
3)Implement the listener in your activity
3)在你的活动中实现监听器
public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener {
//your code here
}
4)Override the OnFragmentInteraction in the activity
4)覆盖活动中的 OnFragmentInteraction
@Override
public void onFragmentInteraction(int id) {
Log.d(TAG, "received from fragment: " + id);
}
More info on it: https://developer.android.com/training/basics/fragments/communicating.html
关于它的更多信息:https: //developer.android.com/training/basics/fragments/communicating.html
回答by ZeWolfe15
One easy way I found was the following: Implement this is your dialogFragment,
我发现的一种简单方法如下:实现这是您的 dialogFragment,
CallingActivity callingActivity = (CallingActivity) getActivity();
callingActivity.onUserSelectValue("insert selected value here");
dismiss();
And then in the activity that called the Dialog Fragment create the appropriate function as such:
然后在调用对话框片段的活动中创建适当的函数,如下所示:
public void onUserSelectValue(String selectedValue) {
// TODO add your implementation.
Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show();
}
The Toast is to show that it works. Worked for me.
Toast 是为了表明它有效。为我工作。
回答by Adil Hussain
I'm very surprised to see that no-one has suggested using local broadcasts for DialogFragment
to Activity
communication! I find it to be so much simpler and cleaner than other suggestions. Essentially, you register for your Activity
to listen out for the broadcasts and you send the local broadcasts from your DialogFragment
instances. Simple. For a step-by-step guide on how to set it all up, see here.
我很惊讶的看着利用当地广播,对于没有人提出DialogFragment
来Activity
沟通!我发现它比其他建议简单得多。本质上,您注册Activity
以监听广播并从您的DialogFragment
实例发送本地广播。简单的。有关如何设置所有内容的分步指南,请参见此处。
回答by Malachiasz
Or share ViewModel like showed here:
或者像这里显示的那样共享 ViewModel:
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
public void select(Item item) {
selected.setValue(item);
}
public LiveData<Item> getSelected() {
return selected;
}
}
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// Update the UI.
});
}
}
https://developer.android.com/topic/libraries/architecture/viewmodel#sharing_data_between_fragments
https://developer.android.com/topic/libraries/architecture/viewmodel#sharing_data_between_fragments
回答by Lanitka
In my case I needed to pass arguments to a targetFragment. But I got exception "Fragment already active". So I declared an Interface in my DialogFragment which parentFragment implemented. When parentFragment started a DialogFragment , it set itself as TargetFragment. Then in DialogFragment I called
就我而言,我需要将参数传递给 targetFragment。但我得到了异常“片段已经激活”。所以我在我的 DialogFragment 中声明了一个接口,它的 parentFragment 实现了。当 parentFragment 启动 DialogFragment 时,它会将自己设置为 TargetFragment。然后在 DialogFragment 我叫
((Interface)getTargetFragment()).onSomething(selectedListPosition);
回答by Irvin Joao
In Kotlin
在科特林
// My DialogFragment
class FiltroDialogFragment : DialogFragment(), View.OnClickListener {
类 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()
}
}
}
}
}
// My Activity
// 我的活动
class MyActivity: AppCompatActivity(),FiltroDialogFragment.InterfaceCommunicator {
类 MyActivity: AppCompatActivity(),FiltroDialogFragment.InterfaceCommunicator {
override fun sendRequest(value: String) {
// :)
Toast.makeText(this, value, Toast.LENGTH_LONG).show()
}
}
}
I hope it serves, if you can improve please edit it. My English is not very good
我希望它有用,如果你可以改进,请编辑它。我的英文不是很好