androidandroid-datepickerandroid-timepickerdatepickerdialogtimepickerdialog

Android: DatePickerDialog and TimePickerDialog not passing selection


There is a problem with both DatePickerDialog and TimePickerDialog. A user can select a date and a time with the plus or minus buttons. This works. But when the user clicks into the field, he can set a value by keyboard:

picker dialog

But this does not work at all. When the user types in a new value, and clicks the "OK" button, the value of the currently selected field will not be passed to the onDateSet method. This works neither in DatePickerDialog nor in TimePickerDialog. Instead the user needs to click the green forward button on the keyboard to really set the value in the DatePickerDialog. When he presses "OK" then, the value is passed, but this is a pretty idiotic usability. Nobody would do this. This is how I implement the fragments:

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener
{
    private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @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);
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int day)
    {
        final Calendar calendar = Calendar.getInstance(Locale.getDefault());
        calendar.set(year, month, day);
        String pickedDate = dateFormat.format(calendar.getTime());

        ((MenuEditActivity)getActivity()).setMenuDate(pickedDate);
    }

    @Override
    public void onCancel(DialogInterface dialog)
    {
        super.onCancel(dialog);
    }
}

Did anybody have the same issue and already implement some quick workaround? (I'd rather not want to reimplement the whole Picker dialogs, just of this half-baked implementation).


Solution

  • I found a workaround for DatePickerDialog to disable the keyboard, so the user cannot type date by keyboard. (see also [Disable keyboard input on Android TimePicker)

       public class MyDatePickerDialog extends DatePickerDialog
        {
            public MyDatePickerDialog(Context context, OnDateSetListener listener, int year, int month, int dayOfMonth)
            {
                super(context, listener, year, month, dayOfMonth);
            }
    
            @NonNull
            @Override
            public DatePicker getDatePicker()
            {
                return super.getDatePicker();
            }
        }
    

    in fragment....

    final MyDatePickerDialog datePickerDialog = new MyDatePickerDialog(getActivity(), this, year, month, day);
    datePickerDialog.getDatePicker().setDescendantFocusability(DatePicker.FOCUS_BLOCK_DESCENDANTS);
    

    But this is not possible with TimePickerDialog since there is no method to get the TimePicker, so I used another workaround for time picker, thanks to Mike M.

    public class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener
    {
        private TimePickerDialog timePickerDialog;
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState)
        {
            //Default 6:00
            timePickerDialog = new TimePickerDialog(getActivity(), this, 6, 0, android.text.format.DateFormat.is24HourFormat(getActivity()));
    
            return timePickerDialog;
        }
    
        @Override
        public void onStart()
        {
            super.onStart();
    
            final View hourView = timePickerDialog.findViewById(Resources.getSystem().getIdentifier("hour", "id", "android"));
            final View minuteView = timePickerDialog.findViewById(Resources.getSystem().getIdentifier("minute", "id", "android"));
    
            if (hourView != null && hourView instanceof NumberPicker)
            {
                ((NumberPicker) hourView).setDescendantFocusability(TimePicker.FOCUS_BLOCK_DESCENDANTS);
            }
    
            if (minuteView != null && minuteView instanceof NumberPicker)
            {
                ((NumberPicker) minuteView).setDescendantFocusability(TimePicker.FOCUS_BLOCK_DESCENDANTS);
            }
        }
    
        @Override
        public void onTimeSet(TimePicker view, int hourOfDay, int minute)
        {
            ((MenuEditActivity) getActivity()).setRecipeTime(hourOfDay, minute);
        }
    
        @Override
        public void onCancel(DialogInterface dialog)
        {
            super.onCancel(dialog);
        }
    }