3

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).

Bevor
  • 8,396
  • 15
  • 77
  • 141
  • Well, I don't observe the behavior you describe, but if you wanna try the focusability trick with the `TimePickerDialog`, you should be able to get the `TimePicker` using a method similar to the one shown in [this answer](http://stackoverflow.com/a/39071972). You'd call `findViewById()` on your `TimePickerDialog` instead, use `"timePicker"` in place of `"ampm_layout"`, and the returned `View` should be the `TimePicker`. (You'd omit the visibility stuff, obviously.) You might need to do this in the `Fragment`'s `onStart()` method, to make sure everything's been initialized correctly first. – Mike M. Nov 12 '16 at 04:56
  • 1
    @MikeM. Thanks, it works now (see my updated question). If you post it as answer, I can accept it. Btw., it's strange. I already tried something similar yesterday, but I always got null. Maybe it was, because I didn't do it in `onStart()`. – Bevor Nov 12 '16 at 08:53
  • No problem. Yeah, I got a chance to run a quick test earlier, and it didn't play nice in `onCreateDialog()`. I didn't really investigate the reason, but it worked just fine in `onStart()`. Anyhoo, your fleshed out solutions are much better than my little suggestion. You should transfer those edits to an answer instead. Thank you, though. Appreciate the offer. Cheers! – Mike M. Nov 12 '16 at 09:20

2 Answers2

2

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);
    }
}
Community
  • 1
  • 1
Bevor
  • 8,396
  • 15
  • 77
  • 141
0

This worked for me:

@SuppressWarnings("deprecation")
@Override
public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {
    timePicker.requestFocus();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        hour = timePicker.getHour();
        minute = timePicker.getMinute();
    } else {
        hour = timePicker.getCurrentHour();
        minute = timePicker.getCurrentMinute();
    }
}
david72
  • 7,151
  • 3
  • 37
  • 59