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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:24:10  来源:igfitidea点击:

Receive result from DialogFragment

androiddialogandroid-fragmentsfragmentdismiss

提问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 DismissListenerand giving the DialogFragment a reference to the activity. The Dialog then calls the OnDimissmethod 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 DialogFragmentadd 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/Fragmentthat "called" the DialogFragmentsimply implement this interface.

Activity/ FragmentActivity/Fragment说:“所谓的”DialogFragment简单地实现这个接口。

In your DialogFragmentall you need to add at the point where you'd like to dismiss the DialogFragmentand 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 requestCodeis 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 resultCodewhich I've set to resultCode = 1;in this case.

就是这样。请注意, resultCode 被定义为int resultCoderesultCode = 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 Fragmentand not Activity. So in order to do this you need to use implement an InterfaceCommunicator.

设定目标Fragment而不是Activity。所以为了做到这一点,你需要使用实现一个InterfaceCommunicator.

In your DialogFragmentset 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 Activitywhen the DialogFragmentis 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 implementsclause at the very top of your class:

然后实现接口就大功告成了。您可以通过implements将以下行添加到班级最顶部的子句中来做到这一点:

public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator

And then @Overridethe 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 DialogFragmentsand 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 DialogFragmentfrom 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 categoryDialogis my DialogFragmentwhich i want to call and after this in your implementation of dialogfragmentplace this code where you are setting your data in intent. The value of resultCodeis 1 you can set it or use system Defined.

我想调用的categoryDialogmy在哪里DialogFragment,然后在您执行dialogfragment此代码的地方,您打算在其中设置数据。的值为resultCode1,您可以设置它或使用系统定义。

            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 resultCodeand requestCodein 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 DialogFragmentto Activitycommunication! I find it to be so much simpler and cleaner than other suggestions. Essentially, you register for your Activityto listen out for the broadcasts and you send the local broadcasts from your DialogFragmentinstances. Simple. For a step-by-step guide on how to set it all up, see here.

我很惊讶的看着利用当地广播,对于没有人提出DialogFragmentActivity沟通!我发现它比其他建议简单得多。本质上,您注册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

我希望它有用,如果你可以改进,请编辑它。我的英文不是很好