What is the \"correct\" way to return the values to the calling activity from a complex custom dialog - say, text fields, date or time picker, a bunch of radio buttons, etc,
I will explain one solution with the example of two fragments. Imagine there is a SimpleFragment which has just one text field to render a date. Then there is a DatePickerFragment which allows to choose a particular date. What I want is that the DatePickerFragment passes the date value back to the calling SimpleFragment whenever the user confirms her selection.
So, first of all we start the DatePickerFragment from within the SimpleFragment:
private DateTime mFavoriteDate; // Joda-Time date
private void launchDatePicker() {
DatePickerFragment datePickerFragment = new DatePickerFragment();
Bundle extras = new Bundle();
// Pass an initial or the last value for the date picker
long dateInMilliSeconds = mFavoriteDate.getMillis();
extras.putLong(BundleKeys.LAST_KNOWN_DATE, dateInMilliSeconds);
datePickerFragment.setArguments(extras);
datePickerFragment.setTargetFragment(this, SIMPLE_FRAGMENT_REQUEST_CODE);
datePickerFragment.show(getActivity().getSupportFragmentManager(),
DatePickerFragment.FRAGMENT_TAG);
}
In the dialog fragment we prepare to pass back the selected date when the user hits the positive button:
public static final String DATE_PICKED_INTENT_KEY = "DATE_PICKED_INTENT_KEY";
public static final int DATE_PICKED_RESULT_CODE = 123;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// ...
Long dateInMilliSeconds = getArguments().getLong(BundleKeys.LAST_KNOWN_DATE);
DateTime date = new DateTime(dateInMilliSeconds);
initializePickerUiControl(date);
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity);
dialogBuilder
.setPositiveButton(R.string.date_picker_positive, (dialog, which) -> {
// Pass date to caller
passBackDate();
})
.setNegativeButton(R.string.date_picker_negative, (dialog, which) -> {
// Nothing to do here
});
return dialogBuilder.create();
}
private void passBackDate() {
DateTime dateTime = getDateTimeFromPickerControl();
Intent intent = new Intent();
intent.putExtra(DATE_PICKED_INTENT_KEY, dateTime.getMillis());
getTargetFragment().onActivityResult(
getTargetRequestCode(), DATE_PICKED_RESULT_CODE, intent);
}
Back in the requesting fragment we consume what has been passed back by the dialog:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SIMPLE_FRAGMENT_REQUEST_CODE &&
resultCode == DatePickerFragment.DATE_PICKED_RESULT_CODE) {
long datePickedInMilliseconds = data.getLongExtra(
DatePickerFragment.DATE_PICKED_INTENT_KEY, 0);
mFavoriteDate = new DateTime(datePickedInMilliseconds);
updateFavoriteDateTextView();
}
else {
super.onActivityResult(requestCode, resultCode, data);
}
}
References to mattpic who gave an excellent answer before.