Can't get Android DatePickerDialog to switch to Spinner mode
Asked Answered
O

4

17

I am building an app that uses a DatePickerDialog to allow the user to select their birthdate. Here's the code that loads the dialog right now:

private void selectBirthdate() {
    int year, month, day;
    if (mBirthDate == null) {
        year = DEF_YEAR;
        month = DEF_MON;
        day = DEF_DAY;
    }
    else {
        year = mBirthDate.get(Calendar.YEAR);
        month = mBirthDate.get(Calendar.MONTH);
        day = mBirthDate.get(Calendar.DAY_OF_MONTH);
    }
    new DatePickerDialog(
            getActivity(),
            new DatePickerDialog.OnDateSetListener() {
                @Override
                public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                    mBirthDate = new GregorianCalendar();
                    mBirthDate.set(Calendar.YEAR, year);
                    mBirthDate.set(Calendar.MONTH, month);
                    mBirthDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
                    if (mTxtBirthDate != null) {
                        mTxtBirthDate.setText(mBirthDateFormat.format(mBirthDate.getTime()));
                    }
                }
            },
            year,
            month,
            day
    ).show();
}

And here's what the dialog looks like when I load it: Original Dialog

However, they want to be able to use the old-style spinner DatePicker, because in the new Calendar view, it's not always obvious to the user that they can change the year. So I have been studying up on the topic, and according to what I have read, it should be possible to use themes to force the DatePickerDialog into Spinner mode. So here's what I've done.

First, I added the following to my styles.xml: Style XML

(Sorry for the screenshot. Apparently SO's parser can't handle XML.)

Then, I update the DatePickerDialog constructor to use my new style:

new DatePickerDialog(
        getActivity(),
        R.style.MyDialogTheme,
        new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                mBirthDate = new GregorianCalendar();
                mBirthDate.set(Calendar.YEAR, year);
                mBirthDate.set(Calendar.MONTH, month);
                mBirthDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
                if (mTxtBirthDate != null) {
                    mTxtBirthDate.setText(mBirthDateFormat.format(mBirthDate.getTime()));
                }
            }
        },
        year,
        month,
        day
).show();

Now, when I load the dialog it looks like this: New Dialog

Clearly something has changed; the dialog has a darker theme. But it's not doing what I want. It's still displaying the calendar view instead of the spinner view. Any idea what I might have missed?

Okwu answered 7/6, 2017 at 16:26 Comment(0)
U
30

Here is what worked for me:

1) Create these two styles in your style.xml

<style name="MySpinnerDatePickerStyle" parent="android:Theme.Material.Dialog">
    <item name="android:datePickerStyle">@style/MySpinnerDatePicker</item>
</style>

<style name="MySpinnerDatePicker" parent="android:Widget.Material.DatePicker">
    <item name="android:datePickerMode">spinner</item>
</style>

2) Set "MySpinnerDatePickerStyle" as your style in your new DatePickerDialog

DatePickerDialog datePickerDialog = new DatePickerDialog(myContext, R.style.MySpinnerDatePickerStyle, date, myCalendar
                    .get(Calendar.YEAR), myCalendar.get(Calendar.MONTH),
                    myCalendar.get(Calendar.DAY_OF_MONTH));

Hope this works for you.. Note: I am still trying to figure out how to style the spinner by changing color and text color

Unlimited answered 29/7, 2017 at 23:39 Comment(4)
Customize colors doesn't work because your parent is from android: , so you need to set independent tags inside it like: <item name="android:colorAccent">@color/colorAccent</item>Lafferty
requires API level 21, so no go for those who's minimum is level 19Turnpike
set background color by adding <item name="android:backrgound">@color/[reference to a color item]</item> under datePickerMode itemTeatime
Other resources online suggest setting android:datePickerMode="spinner" and android:calendarViewShown="false" in the xml, and that setting a style is not necessary. Why is this?Rutilant
F
5

Similarly as @Abuzaid said, inside your AppTheme style, add the android:datePickerStyle item as shown in this AppTheme example below:

 <!-- Example of a Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorPrimary</item>

    <!-- !Important! Add this to force the use of the Spinner mode -->
    <item name="android:datePickerStyle">@style/myDatePickerStyle</item>
</style>

Add this style to your styles.xml (inside the values-v21 folder, becouse this option is available only for api 21+)

<style name="myDatePickerStyle" parent="android:Widget.Material.DatePicker">
    <item name="android:datePickerMode">spinner</item>
</style>

For Android version < 21, the spinner mode is the default. For 21+ the calendar mode is the new default mode.

In this case you can omit to specify the dialog theme becouse it will be inferred by the AppTheme that we have. For example: (With Java 8 lambda)

final Calendar cal = Calendar.getInstance();
final DatePickerDialog.OnDateSetListener dateSelectedListener = (view, year, monthOfYear, dayOfMonth) -> {
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.MONTH, monthOfYear+1);
    cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
 };

int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);

DatePickerDialog dp= new DatePickerDialog(context, dateSelectedListener, year, month, day);

Reference: https://developer.android.com/reference/android/app/DatePickerDialog

Hope it can help! :)

Filippa answered 18/1, 2019 at 9:31 Comment(0)
U
2

Using the styles mentioned in the other answer to get the spinner only works on stock (or close to stock) Android devices, such as Pixel, Motorola, OnePlus, etc. I made the mistake of testing on these devices only, and to my surprise, Samsung users were still complaining about the other picker, where they couldn't find how to change the birthdate year without having to scroll month by month.

The only cross device solution is using a library, that way you are sure you get the same spinner picker regardless of the underlying OS. I my case, I used SpinnerDatePicker, which is a pretty straightforward replacement for the native picker.

Unprepared answered 15/2, 2018 at 11:55 Comment(0)
C
1

Simple solution with Material Componente

<style name="SpinnerDatePickerDialogTheme" parent="ThemeOverlay.MaterialComponents.Dialog">
    <item name="android:datePickerStyle">@style/DatePickerStyle</item>
    <item name="colorControlNormal">@color/teal_200</item>
</style>

<style name="DatePickerStyle" parent="@android:style/Widget.Material.Light.DatePicker">
    <item name="android:datePickerMode">spinner</item>
</style>

For some reason ThemeOverlay.MaterialComponents.Dialog.Alert is not working with darkmode

Crofton answered 24/11, 2020 at 1:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.