Get date from datepicker using dialogfragment

AndroidDatepickerAndroid DialogAndroid Datepicker

Android Problem Overview


I'm using the google example to insert a datepicker inside my app using a dialogfragment
http://developer.android.com/guide/topics/ui/controls/pickers.html

But I'm not sure how to get date after set it (not java expert). Dialog and datepicker runs ok and I can log that date is correctely set but, how can i do to get a callback executed on parent activity?

This is my Dialog fragment

public class DatePickerFragment extends DialogFragment implements
		DatePickerDialog.OnDateSetListener {

	@Override
	public Dialog onCreateDialog(Bundle savedInstanceState) {
		// Use the current date as the default date in the picker
		final Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH);
		int day = c.get(Calendar.DAY_OF_MONTH);

		// Create a new instance of DatePickerDialog and return it
		return new DatePickerDialog(getActivity(), this, year, month, day);
	}

	public void onDateSet(DatePicker view, int year, int month, int day) {
		**Log.w("DatePicker","Date = " + year);**
	}
}

...and I call dialog from my activity with...

public void showDatePickerDialog(View v) {
	DialogFragment newFragment = new DatePickerFragment();
	newFragment.show(getSupportFragmentManager(), "datePicker");
}

What is the correct way to call a method in my parent activity instead Log.w? I suppose that is something related with passing a callback as parameter or something but most of references I found on internet are about previous versions without dialogfragments

EDIT: not sure if it's important but parent activity is declared as:

public class EditSessionActivity extends FragmentActivity {

SOLUTION: thanks to Lecho user this is the way to do it

DatePickerFragmennt.class

public class DatePickerFragment extends DialogFragment{

	@Override
	public Dialog onCreateDialog(Bundle savedInstanceState) {
		// Use the current date as the default date in the picker
		final Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH);
		int day = c.get(Calendar.DAY_OF_MONTH);

		// Create a new instance of DatePickerDialog and return it
		return new DatePickerDialog(getActivity(), (EditSessionActivity)getActivity(), year, month, day);
	}

}

...and parent activity EditSessionActivity.class...

public class EditSessionActivity extends FragmentActivity implements OnDateSetListener {
...
	@Override
	public void onDateSet(DatePicker view, int year, int month, int day) {
		//do some stuff for example write on log and update TextField on activity
		Log.w("DatePicker","Date = " + year);
		((EditText) findViewById(R.id.tf_date)).setText("Date = " + year);
	}

Android Solutions


Solution 1 - Android

Constructor fo DatePickerDialog takes DatePickerDialog.OnDateSetListener as second parameter, so maybe you should implement that interface in your parent activity EditSessionActivity (not in DatePickerFragment ) and change this line:

return new DatePickerDialog(getActivity(), this, year, month, day);

into this:

return new DatePickerDialog(getActivity(), (EditSessionActivity)getActivity(), year, month, day);

And then your activity should looks like this:

public class EditSessionActivity extends FragmentActivity implements
        DatePickerDialog.OnDateSetListener{

    public void onDateSet(DatePicker view, int year, int month, int day) {
        //use date in your activity
    }
    ...
}

Solution 2 - Android

I simple override onDateSet in date picker creation in my class that shows a date picker. See code below:

  private OnClickListener onDateClicked() {
    return new OnClickListener() {
          @Override
          public void onClick(View v) {
             DialogFragment newFragment = new DatePickerFragment() {
                @Override
                public void onDateSet(DatePicker view, int year, int month, int day) {
                  salePaymentCustomView.setBtDateText("" + day + "/" + month+1 + "/" + year);
                }
             };
             newFragment.show(getActivity().getSupportFragmentManager(), "datePicker");
    }
  };
 } 

Solution 3 - Android

The problem can also be solved without moving the onDateSet method to the parent activity. You just have to tell the DatePickerFragment where to search for the view:

public class DatePickerFragment extends DialogFragment implements
    DatePickerDialog.OnDateSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the current date as the default date in the picker
        final Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);

        // Create a new instance of DatePickerDialog and return it
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }

    public void onDateSet(DatePicker view, int year, int month, int day) {
        // do some stuff for example write on log and update TextField on activity
        Log.w("DatePicker","Date = " + year);
        ((TextView) getActivity().findViewById(R.id.tf_date)).setText("Date = " + year);
    }
}

I also changed the target of the cast from EditText to TextView. This way, you can reuse your implementation for different kinds of views, not only for an EditText.

Solution 4 - Android

i have one correction to the above answer. instead of return the DatePickerDialog like this > return new DatePickerDialog(getActivity(), (EditSessionActivity)getActivity(), year, month, day);

you should return it in a more generic way

> return new DatePickerDialog(getActivity(), (OnDateSetListener)getActivity(), year, month, day);

just make sure your activity implements OnDateSetListener interface and override the function onDateSet

@Override
public void onDateSet(DatePicker view, int year, int monthOfYear,int dayOfMonth) 

Solution 5 - Android

public void onDate(View view) {

		DialogFragment fragment = new SelectDateFragment();
		fragment.show(getFragmentManager(), "Date Picker");
	}

//	@SuppressLint("NewApi")
	class SelectDateFragment extends DialogFragment implements
			DatePickerDialog.OnDateSetListener {

		public Dialog onCreateDialog(Bundle savedInstanceState) {


			System.out.println("entrering on create dialog");;

			return new DatePickerDialog(getActivity(), this, mYear, mMonth,
					mDay);//it will return dialog setting date with mYera,MMonth and MDay

		}

		@Override
		public void onDateSet(android.widget.DatePicker view, int year,
				int monthOfYear, int dayOfMonth) {
			System.out.println("year=" + year + "day=" + dayOfMonth + "month="
					+ monthOfYear);
			mYear=year;
			mMonth=monthOfYear;
			mDay=dayOfMonth;
			
			onPopulateSet(year, monthOfYear + 1, dayOfMonth);

		}
// set the selected date in the edit text  
		private void onPopulateSet(int year, int i, int dayOfMonth) {
			EditText et_setDate;
			et_setDate = (EditText) findViewById(R.id.register_et_dob);//register_et_dob:-id name of the edit text 
			et_setDate.setText(dayOfMonth + "/" + i + "/" + year);
			System.out.println("enetring on populate Set");

		}

Solution 6 - Android

In case you have to return a result to a Fragment, but not an Activity, here is a complete solution:

public class DatePickerDialogFragment extends DialogFragment  {

    private static final String ARGUMENT_YEAR = "ARGUMENT_YEAR";
    private static final String ARGUMENT_MONTH = "ARGUMENT_MONTH";
    private static final String ARGUMENT_DAY = "ARGUMENT_DAY";
    private DatePickerDialog.OnDateSetListener listener;

    private int year;
    private int month;
    private int dayOfMonth;

    public static DatePickerDialogFragment newInstance(final int year, final int month, final int dayOfMonth) {
        final DatePickerDialogFragment df = new DatePickerDialogFragment();
        final Bundle args = new Bundle();
        args.putInt(ARGUMENT_YEAR, year);
        args.putInt(ARGUMENT_MONTH, month);
        args.putInt(ARGUMENT_DAY, dayOfMonth);
        df.setArguments(args);
        return df;
    }

    @Override
    public void onCreate(@Nullable final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        retrieveArguments();
    }

    private void retrieveArguments() {
        final Bundle args = getArguments();
        if (args != null) {
            year = args.getInt(ARGUMENT_YEAR);
            month = args.getInt(ARGUMENT_MONTH);
            dayOfMonth = args.getInt(ARGUMENT_DAY);
        }
    }

    @Override
    public Dialog onCreateDialog(final Bundle savedInstanceState) {
        return new DatePickerDialog(getContext(), this.listener, this.year, this.month, this.dayOfMonth);
    }

    public void setListener(final DatePickerDialog.OnDateSetListener listener) {
        this.listener = listener;
    }
}

Then just use it in a Fragment or in an Activity:

final Calendar c = Calendar.getInstance();
DatePickerDialogFragment datePicker = DatePickerDialogFragment.newInstance(
        c.get(Calendar.YEAR),
        c.get(Calendar.MONTH),
        c.get(Calendar.DAY_OF_MONTH));
datePicker.setListener(this);
datePicker.show(getChildFragmentManager(), null);

Solution 7 - Android

Leszek's answer works, but not if the Dialog is started from another Fragment. In that case you need to use setTargetFragment() in the code that creates the dialog and getTargetFragment() in the dialog code.

In the code that creates the dialog:

DialogFragment dialogFragment = new YourDialogFragment();
dialogFragment.setTargetFragment(YourParentFragment.this, 0);
dialogFragment.show(getFragmentManager(), "mydialog");

In the DialogFragment code:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
	DatePickerDialog.OnDateSetListener listener = new DatePickerDialog.OnDateSetListener()
	{
		@Override
		public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
		{
			YourParentFragment parentFragment = (YourParentFragment) getTargetFragment();
            // Manipulate the parent fragment
            // ...
		}
	};
    // Get the initial date
    // ...
	return new DatePickerDialog(getActivity(), listener, year, month, day);
}

Solution 8 - Android

I had a similar problem to this, but my date picker was being launched from a dialog fragment inside another fragment. This made it very difficult to play around with the callbacks, because they want to return to the Main Activity and I wanted the data to go back to the previous dialog fragment.

Initially, I passed the new date values to the Main Activity (using the OnDateSetListener) and was going to get them using the dialog that launched the date picker, but there are no lifecycle events triggered in that dialog when the datepicker closes.

The result I came to was in onDismiss in the date picker, instantiate a new dialog fragment, call a set results method on it and then launch it. Of course for this you need to make sure that the previous fragment is dismissed when it launches the date picker.

This is the dialogFragment that called the date picker

public class NewTrialDialogFragment extends DialogFragment  {

public final String LOG_TAG = "NewTrialDialog Fragment";

Button startDateButton;
Integer newYear, newMonth, newDay;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.dialog_new_trial, container, false);
    getDialog().setTitle("Dialog New Trial");

    startDateButton = (Button) rootView.findViewById(R.id.button_start_date);
    startDateButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showDatePickerDialog(v);
        }
    });

    //If you exit the datepicker without choosing anything, it returns zeros
    if (newYear != null && newMonth != null && newDay != null && newYear != 0) {
        startDateButton.setText(newYear + " " + newMonth + " " + newDay);
    }else{
        startDateButton.setText("Select Start Date");
    }

     return rootView;
}

public void showDatePickerDialog(View v) {
    TrialDatePickerDialog newDialog = new TrialDatePickerDialog();
    newDialog.show(getActivity().getSupportFragmentManager(), "datePicker");
    this.dismiss();
}

public void setDates(int year, int month, int day){
    newYear = year;
    newMonth = month;
    newDay = day;
}}

And the date picker

public  class TrialDatePickerDialog extends DialogFragment implements DatePickerDialog.OnDateSetListener
     {

private final String LOG_TAG = "TrialDatePickerDialog";
int newYear, newMonth, newDay;


@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Use the current date as the default date in the picker
    final Calendar c = Calendar.getInstance();
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH);
    int day = c.get(Calendar.DAY_OF_MONTH);

    // Create a new instance of TrialDatePickerDialog and return it
    return new DatePickerDialog(getActivity(), this , year, month, day);
}

         @Override
         public void onDismiss(DialogInterface dialog) {
             super.onDismiss(dialog);
             FragmentManager fm = getActivity().getSupportFragmentManager();
             NewTrialDialogFragment newTrialDialogFragment = new NewTrialDialogFragment();
             newTrialDialogFragment.setDates(newYear, newMonth, newDay);
             newTrialDialogFragment.show(fm, "new_trial_dialog");

         }

         @Override
         public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
             newYear = year;
             newMonth = monthOfYear;
             newDay = dayOfMonth;
         }
     }

Solution 9 - Android

Kotlin version.

DatePickerFragment class:

class DatePickerFragment : DialogFragment() {

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

        val c = Calendar.getInstance()
        val year = c.get(Calendar.YEAR)
        val month = c.get(Calendar.MONTH)
        val day = c.get(Calendar.DAY_OF_MONTH)

        return DatePickerDialog(context!!, context!! as MainActivity, year, month, day)
    }
}

DatePickerDialog.OnDateSetListener is moved to MainActicity

class MainActivity : AppCompatActivity(), DatePickerDialog.OnDateSetListener {

    ..

    override fun onDateSet(view: DatePicker, year: Int, month: Int, day: Int) {
        //use date in your activity
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGonzalo CaoView Question on Stackoverflow
Solution 1 - AndroidLeszekView Answer on Stackoverflow
Solution 2 - AndroidVinicius PaldêsView Answer on Stackoverflow
Solution 3 - AndroidstepsView Answer on Stackoverflow
Solution 4 - AndroidBenny MargalitView Answer on Stackoverflow
Solution 5 - AndroidHarsh ParikhView Answer on Stackoverflow
Solution 6 - AndroidLeonid UstenkoView Answer on Stackoverflow
Solution 7 - AndroidwvdzView Answer on Stackoverflow
Solution 8 - AndroidMattView Answer on Stackoverflow
Solution 9 - AndroidWaterView Answer on Stackoverflow