Search code examples
javaandroiddatedatepickerdatepickerdialog

Update date in Android DatePickerDialog with Today button without closing dialog


I'd like to have a date picker dialog with a "Today" button. If I click on Today button, it should reset datepicker to current date, without closing the dialog.

I have the following code:

Calendar today = Calendar.getInstance();

DatePickerDialog datePickerDialog = new DatePickerDialog(context, R.style.MyDialogStyle, date, myCalendar.get(Calendar.YEAR), myCalendar.get(Calendar.MONTH), myCalendar.get(Calendar.DAY_OF_MONTH));
datePickerDialog.setButton(DialogInterface.BUTTON_NEUTRAL, "Today", (dialog, which) -> {
      datePickerDialog.updateDate(today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DAY_OF_MONTH));
});
datePickerDialog.show();

Expected behavior: set datepicker's date to current date without closing the dialog.

Actual behavior: dialog closes, date doesn't change.

I also tried with new DatePickerDialog(...), and

datePickerDialog.getDatePicker().init(today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DAY_OF_MONTH), null);

but it still doesn't work, only closes the dialog. What am I missing here?

Is there a way to update datepicker's date programmatically without closing the dialog?


Solution

  • By default click button calls also dismiss() method to close the DatePickerDialog. It applies also to the DialogInterface.BUTTON_NEUTRAL button which you use for 'Today'.

    Probably the simplest way to avoid this is to override the DatePickerDialog.dismiss() method and skip calling super.dismiss() if the 'Today' button was clicked. Here is my working code in Kotlin I use for the same purpose (Today button for the DatePickerDialog). I use skipDismiss flag to know when to skip dismissal.

    val datePickerDialog = object : DatePickerDialog(
            this@MainActivity,
            settings.currentTheme,
            DatePickerDialog.OnDateSetListener { _, chosenYear, chosenMonth, dayOfMonth ->
                calendar.set(Calendar.YEAR, chosenYear)
                calendar.set(Calendar.MONTH, chosenMonth)
                calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
                text_view_chosen_date.text = SimpleDateFormat("dd/MM/yyyy", Locale.US).format(calendar.time)
            },
            calendar.get(Calendar.YEAR),
            calendar.get(Calendar.MONTH),
            calendar.get(Calendar.DAY_OF_MONTH)
    ) {
        override fun dismiss() {
            if (!skipDismiss) {
                super.dismiss()
            } else {
                skipDismiss = false
            }
        }
    }
    

    And of course the 'Today' button listener should set the skipDismiss flag to true when called. Here is my code for that:

    datePickerDialog.setButton(DialogInterface.BUTTON_NEUTRAL, "Today") { dialog, which ->
        val today = Calendar.getInstance()
        (dialog as DatePickerDialog).updateDate(
                today.get(Calendar.YEAR),
                today.get(Calendar.MONTH),
                today.get(Calendar.DAY_OF_MONTH)
        )
        skipDismiss = true;
    }