16

After Lollipop, DatePicker having a very beautiful calenderview to select the date. But the issue is selecting year. Most of the common people facing trouble to selecting year. They just scrolling. It take too long time to scroll for changing years. So I need to show year selection first when open Datepicker Dialog in android.

The Datepicker normally opening like below one:

enter image description here

But it should be start from year selection. like below one:

enter image description here

  • please refer this link https://github.com/wdullaer/MaterialDateTimePicker use this showYearPickerFirst method – iAndroid Jul 20 '16 at 09:20
  • 1
    Thanks. Successfully got with MaterialDateTimePicker plugin –  Jul 21 '16 at 16:13
  • 3
    This is such a common issue, I receve several support emails every week from users telling me how the date picker is silly because they have to scroll through 40 years. Starting with year could possibly fix this. But I think this dialog has bad UX. – Zapnologica Feb 04 '17 at 08:13

7 Answers7

32

You can get a reference to year view and then just simulate user click to open it.

dataPicker.getTouchables().get( 0 ).performClick();

UPDATE: If not clear I will explain every step. You need to have datePicker reference first. With datePicker reference you can get datePicker components with getTouchables() method. Component year is at the first place so need to call .get(0) to get a reference to year. And after that just simulate user click to open years view at the start rather than waiting user to click on it.

Matej Vukosav
  • 666
  • 8
  • 12
  • More specific with what exactly? If not clear I will explain every step. He need to have datePicker reference first. With datePicker reference he can get datePicker components with getTouchables() method. Component year is at the first place so need to call get(0) to get a reference to it. And after that just simulate user click to open years view at the start rather than waiting user to click on it. – Matej Vukosav Sep 14 '17 at 16:16
  • 3
    This is the greatest workaround I have found in 6 years on Android. Awesome! – andude Dec 01 '17 at 23:23
7

Extending on @MatejVukosav answer

 if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        LogUtil.LogToConsole(TAG, "Date picker select");
        datePickerDialog.getDatePicker().getTouchables().get(1).performClick();
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        LogUtil.LogToConsole(TAG, "Date picker select post lollipop");
        datePickerDialog.getDatePicker().getTouchables().get(0).performClick();
    }

and then you show the dialog.

4

Expanding on @Giovanny Piñeros answer I'd like to propose to iterate through all the touchables and select the corresponding one by id, to guarantee that the correct view will be selected.

int viewId = 0;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            viewId = Resources.getSystem().getIdentifier("date_picker_year",  "id", "android");
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            viewId = Resources.getSystem().getIdentifier("date_picker_header_year",  "id", "android"); 
}

Then, if (viewId > 0), we can iterate through datePickerDialog.getDatePicker().getTouchables() and compare their id to viewId.

Kurovsky
  • 1,081
  • 10
  • 25
3

There is not very reliable way to do that:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    DatePicker datePicker = (DatePicker) findViewById(R.id.test);

    openYearView(datePicker);
}

private void openYearView(DatePicker datePicker) {
    try {
        Field mDelegateField = datePicker.getClass().getDeclaredField("mDelegate");
        mDelegateField.setAccessible(true);
        Object delegate = mDelegateField.get(datePicker);
        Method setCurrentViewMethod = delegate.getClass().getDeclaredMethod("setCurrentView", int.class);
        setCurrentViewMethod.setAccessible(true);
        setCurrentViewMethod.invoke(delegate, 1);
    } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
    }
}
Divers
  • 9,531
  • 7
  • 45
  • 88
1

For future reference, kotlin users, based on existing answers on this thread.

    var viewId = 0
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        viewId = Resources.getSystem().getIdentifier("date_picker_year", "id", "android")
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        viewId = Resources.getSystem().getIdentifier("date_picker_header_year", "id", "android")
    }

    yourDatePickerDialog.show()


    for (touchable in yourDatePickerDialog.getDatePicker().getTouchables()) {
        if (touchable.id.equals(viewId))
        {
            touchable.performClick()
            break
        }

    }
0

I'm using react-native and the DateTimePicker component has the display="spinner" option. In this case, the calendar renders like the picture below.

enter image description here

papadi
  • 985
  • 2
  • 9
  • 22
0

You can do it by including just one single line before your dialog.show()

    editext.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            calendar=Calendar.getInstance();
            int day=calendar.get(Calendar.DAY_OF_MONTH);
            int month=calendar.get(Calendar.MONTH);
            int year=calendar.get(Calendar.YEAR);
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            datePickerDialog=new DatePickerDialog(ActivityDoctorDetails.this, R.style.DialogTheme, new DatePickerDialog.OnDateSetListener() {
                @Override
                public void onDateSet(DatePicker datePicker, int m_year, int m_month, int m_day) {
                    String Mday, Mmonth, Myear;

                    Mday=Integer.toString(m_day);
                    Mmonth=Integer.toString(m_month);

                    if (m_day < 10) {
                        // editTextDate.setText("0"+m_day+"/"+m_month+"/"+m_year);
                        Mday="0" + Integer.toString(m_day);
                    }
                    if (m_month < 10) {
                        //editTextDate.setText(m_day+"/"+"0"+m_month+"/"+m_year);
                        Mmonth="0" + Integer.toString(m_month);

                    }
                    if (m_day < 10 && m_month < 10) {
                        //editTextDate.setText("0" + m_day + "/" + "0" + m_month + "/" + m_year);
                        Mday="0" + Integer.toString(m_day);
                        Mmonth="0" + Integer.toString(m_month);


                    }
                    if (m_day > 10 && m_month < 10) {
                        //editTextDate.setText(m_day+"/"+"0"+m_month+"/"+m_year);
                        Mmonth="0" + Integer.toString(m_month);
                        Mday=Integer.toString(m_day);


                    }
                    if (m_day < 10 && m_month > 10) {
                        //editTextDate.setText(m_day+"/"+"0"+m_month+"/"+m_year);
                        Mday="0" + Integer.toString(m_day);
                        Mmonth=Integer.toString(m_month);

                    }

                    editext.setText(m_year + "/" + Mmonth + "/" + Mday);


                }
            }, day, month, year);
            //datePickerDialog.getDatePicker().setMinDate(System.currentTimeMillis() - 1000);
            datePickerDialog.getDatePicker().getTouchables().get(0).performClick();
            datePickerDialog.show();
        }