trickedoutdavid trickedoutdavid - 5 months ago 72
Android Question

How to send data from DialogFragment to a Fragment?

I have a fragment that opens a dialogfragment to get user input (a string, and an integer). How do I send these two things back to the fragment?

Here is my DialogFragment:

public class DatePickerFragment extends DialogFragment {
String Month;
int Year;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getDialog().setTitle(getString(R.string.Date_Picker));
View v = inflater.inflate(R.layout.date_picker_dialog, container, false);

Spinner months = (Spinner) v.findViewById(R.id.months_spinner);
ArrayAdapter<CharSequence> monthadapter = ArrayAdapter.createFromResource(getActivity(),
R.array.Months, R.layout.picker_row);
months.setAdapter(monthadapter);
months.setOnItemSelectedListener(new OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int monthplace, long id) {
Month = Integer.toString(monthplace);
}
public void onNothingSelected(AdapterView<?> parent) {
}
});

Spinner years = (Spinner) v.findViewById(R.id.years_spinner);
ArrayAdapter<CharSequence> yearadapter = ArrayAdapter.createFromResource(getActivity(),
R.array.Years, R.layout.picker_row);
years.setAdapter(yearadapter);
years.setOnItemSelectedListener(new OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int yearplace, long id) {
if (yearplace == 0){
Year = 2012;
}if (yearplace == 1){
Year = 2013;
}if (yearplace == 2){
Year = 2014;
}
}
public void onNothingSelected(AdapterView<?> parent) {}
});

Button button = (Button) v.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getDialog().dismiss();
}
});

return v;
}
}


I need to send the data after the button click and before getDialog().dismiss()

Here is the fragment that data needs to be sent to:

public class CalendarFragment extends Fragment {
int Year;
String Month;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

int position = getArguments().getInt("position");
String[] categories = getResources().getStringArray(R.array.categories);
getActivity().getActionBar().setTitle(categories[position]);
View v = inflater.inflate(R.layout.calendar_fragment_layout, container, false);

final Calendar c = Calendar.getInstance();
SimpleDateFormat month_date = new SimpleDateFormat("MMMMMMMMM");
Month = month_date.format(c.getTime());
Year = c.get(Calendar.YEAR);

Button button = (Button) v.findViewById(R.id.button);
button.setText(Month + " "+ Year);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new DatePickerFragment().show(getFragmentManager(), "MyProgressDialog");
}
});
return v;
}
}


so once the user selects a date in the dialogfragment, it must return the month and year.

Then, the text on the button should change to the month and year specified by user.

Answer

Here's the recipe:

  1. Create Interface (i.e. MyDialogCallbackContract) with the method to be used to pass the data you need back to invoking Fragment (i.e. methodToPassDataBackToFragment(... data);).
  2. Ensure your DialogFragment (or "ordinary" Fragment, as the same recipe can be used to pass data from Fragment back to host Activity or parent Fragment) implements this interface: class MyFragment extends Fragment implements MyDialogCallbackContract {....}
  3. Upon creation of DialogFragment set your invoking Fragment as DialogFragment's target by calling myDialogFragment.setTargetFragment(this, 0);.
  4. In your DialogFragment, get that fragment object with getTargetFragment(); and cast into the interface you created to ensure that fragments implements the interfce: MyDialogCallbackContract mHost = (MyDialogCallbackContract)getTargetFragment();. Note you will get ClassCastException if your target fragment is not implementing MyDialogCallbackContract interface, but I personally let my code crash here by not catching this exception, because this is what should never really.
  5. When time comes, call methodToPassData() to pass data you want, i.e. like this ((MyDialogCallbackContract)getTargetFragment()).methodToPassDataBackToFragment(data);. If you did cast target fragment already in onAttach(), then this code would be just mHost.methodToPassDataBackToFragment(data);.
  6. VoilĂ . You just successfully passed your data from dialog back to invoking fragment.
Comments