8

I found DatePicker(Dialog) very confusing... When setMinDate() is set... the shown calendar really "visually disable" passed dates (make them gray) but these dates are still posible to select! I want to user prevent to do so. Ideal way would be make passed dates non-clickable / unselectable. If it is not possible, than at least catch this event (which one? onDateChanged?, onSelected? ...) and toast a message and disable OK button until user selects a valid date.

Unfortunatelly, datepicker(dialog) has no onChangedListener (actually it has but has no setter for it). So the only event I get is on OK button pressed. It is too late.

Here is my code

    dateTextView = (TextView) view.findViewById(R.id.createOrder_date);
    dateTextView.setText(R.string.createOrder_time_now);
    dateTextView.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            final Calendar calendarNow = Calendar.getInstance();
            final int yearNow = calendarNow.get(Calendar.YEAR);
            final int monthNow = calendarNow.get(Calendar.MONTH);
            final int dayNow = calendarNow.get(Calendar.DAY_OF_MONTH);

            DatePickerDialog datePickerDialog = new DatePickerDialog(CreateOrderFragment.this.getActivity(), new DatePickerDialog.OnDateSetListener() {
                @Override
                public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.set(year, monthOfYear, dayOfMonth);

                    if (calendar.before(calendarNow)) {
                        Toast.makeText(CreateOrderFragment.this.getActivity(), getResources().getString(R.string.createOrder_datePicker_selectFutureDate), Toast.LENGTH_SHORT).show();
                        view.updateDate(yearNow, monthNow, dayNow);
                        calendar = calendarNow;
                    }

                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    dateTextView.setText(sdf.format(calendar.getTime()));
                }
            }, yearNow, monthNow, dayNow);

            datePickerDialog.getDatePicker().setMinDate(System.currentTimeMillis() - 1000);
            datePickerDialog.setTitle(getResources().getString(R.string.createOrder_datePicker_title));
            datePickerDialog.show();

        }
    });

enter image description here

Wooff
  • 1,091
  • 12
  • 23
  • `SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");` `Date minDate = null;` `try {` `minDate = sdf.parse("01/01/2014");` `} catch (ParseException e) {` `e.printStackTrace();` `return;` ` }` ::: I did it using this. **NOTE:** It's for API Level 9 and above – Tushar Gogna Feb 23 '15 at 09:26
  • Since Android 6 (sdk23) it is working correctly. So, I deployed same app to lollipop and marshmallow. Lollipop allow to select forbidded date, marshmallow does not allow user to select forbidded date - which is desired behavior. – Wooff Mar 14 '16 at 12:46

2 Answers2

1

When you receive the date in onDateSent(), just check if it's earlier than the date you set in setMinDate(). If so, then just show the DatePickerDialog again.

Code:

final long tomorrow = System.currentTimeMillis() + DateUtils.MILLIS_IN_DAY;

private void showDatePickerDialog()
{
    mDatePickerDialog = new DatePickerDialog(getActivity(), new DatePickerDialog.OnDateSetListener()
    {
        @Override
        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
        {
            Calendar calendar = Calendar.getInstance();
            calendar.set(year, monthOfYear, dayOfMonth);

            //kv If user tries to select date in past (or today)
            if (calendar.getTimeInMillis() < tomorrow)
            {
                //kv Make them try again
                showDatePickerDialog();

                Toast.makeText(this, "Invalid date, please try again", Toast.LENGTH_LONG).show();
            }
            else
            {
                //success
            }
        }
    }, calendarTwoWeeksInFuture.get(Calendar.YEAR), calendarTwoWeeksInFuture.get(Calendar.MONTH), calendarTwoWeeksInFuture.get(Calendar.DAY_OF_MONTH));

    //kv Set minimum date as tomorrow
    mDatePickerDialog.getDatePicker().setMinDate(tomorrow);

    mDatePickerDialog.show();
}
Karim Varela
  • 7,562
  • 10
  • 53
  • 78
  • Unfortunatelly, it is not very user friendly. It does not solve problem that it let user select invalid date. The solution should be that invalid date must not be possible to select. Either by UI (that it date is not selectable) or immediate action (after user select invalid date - validation message is shown (toast?) and the last choose valid date is selected). – Wooff May 27 '15 at 06:10
  • I know it's not the idea solution, but it works. It doesn't allow the user to continue and shows a Toast if the date selected is invalid. – Karim Varela May 27 '15 at 10:00
0

i have been looking for a while and there seem to be no way to do that in new datePickerDialog (5+) you can handle it yourself by rather returning the min/max value from on click or by reopening the dialog, its up to developer now.

nosaiba darwish
  • 1,179
  • 11
  • 13