19

I'm trying to make a Fragment to show a Dialog using DialogFragment API.

My dialog only has an EditText view and I want to pass the string wrote on it back to the Fragment.

I'm able to show the dialog from the Fragment, but I'm not able to retrieve the string from the input field back to my Fragment.

I tried both ways to create a dialog: overwriting the DialogFragment.onCreateView method and writing the entire dialog's view and overwriting the DialogFragment.onCreateDialog and using the AlertDialog.Builder to make it easier to write the buttons behavior.

The Android documentation about dialogs passing events back to dialog's host is about host being always an Activity and never a Fragment. I tried to generalize the behavior for use it on my case, but I cannot.

I tried using the DialogFragment.onAttach callback to get the Activity reference and use an interface between the Fragment and the DialogFrament and it works fine, but I cannot retrieve the Fragment from the Activity to make it work.

Can anybody help with a brief example?

Thanks in advance

gunar
  • 14,660
  • 7
  • 56
  • 87
JoseLSegura
  • 3,830
  • 3
  • 20
  • 27

2 Answers2

45

You can use the setTargetFragment and getTargetFragment methods of Fragment. You can set your Fragment as the target of the DialogFragment and then retrieve a reference to it from within the DialogFragment.

patheticpat
  • 861
  • 6
  • 11
  • 3
    It works like a charm. A lot of thanks. The second (and optional) argument for `setTargetFragment` is only needed if I go through the `Activity`, isn't it? – JoseLSegura Dec 25 '12 at 17:42
  • 1
    Wow, the dev docs are pretty misleading here and say you should not do direct fragment communication :https://developer.android.com/training/basics/fragments/communicating.html yet there is an api for exactly this purpose! – Sam Mar 28 '14 at 19:22
  • 2
    @Sam I think those docs are talking more about direct communication between different fragments in a multi-pane layout. Consider an activity that shows two fragments in landscape mode but only one of those fragments in portrait mode. If the two fragments directly interacted with one another, things would get messy fast (since you'd have to write extra code that determines whether or not the two fragments are shown at the same time). It would be better to go through the activity (which we know will always exist no matter what) in this case. – Alex Lockwood May 27 '14 at 22:56
  • 2
    @Sam On the other hand, for this particular question it sounds like the original fragment is tightly coupled with the dialog fragment, so it makes sense to use `setTargetFragment` and `getTargetFragment`. – Alex Lockwood May 27 '14 at 23:00
  • Will setTargetFragment() and getTargetFragment method hold true in case of config change where you don't create the dialogFragment but the system restores it for you (if in case the dialog was showing on screen before the config changed)? I don't think so. You will have manually set the target fragment on the restored dialogFragment some how to have the getTargetFragment() working. – Akh Jul 14 '16 at 00:07
  • @AKh The target Fragment is retained across configuration changes. You don't need to call `setTargetFragment` again after everything is restored. – pumpkinpie65 Dec 07 '16 at 19:57
3

you can use callbacks. just implement a "done" button or something like that in your dialogfragment.

so in your dialogfragment do something like this:

protected OnDialogClickedListener callback = null;

public interface OnDialogClickedListener {
    public abstract void onDialogClicked(int position);
}

public void setOnDialogClickedListener(OnDialogClickedListener l){
    callback = l;
}

button.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
        callback.onDialogClicked(position);
        dismiss();
    }
});

in your activity do something like this:

final YourFragment f = YourFragment .newInstance(0);
f.show(ft, "YourFragment ");
f.setOnDialogClickedListener(new OnDialogClickedListener() {
    @Override
    public void onDialogClicked(int position) {
        updateText(position);
        f.dismiss();
    }
});
ha1ogen
  • 13,375
  • 3
  • 19
  • 19
  • It is easy, but I don't want to modify the `Activity` class because two reasons: first is that it a `PreferenceActivity` and the fragments are loaded from a XML resource definition. And second, it is very coupling to attach the behavior of the relationship between two classes to a third. I already made this using a `PreferenceFragment`, but using a "pure" `Fragment` doesn't work. – JoseLSegura Dec 25 '12 at 14:51
  • 4
    This is exactly how you should NOT do this. You are not respecting the fragment lifecycle. See the accepted answer and the official docs on fragment communication: http://developer.android.com/training/basics/fragments/communicating.html – enl8enmentnow Dec 16 '15 at 14:02