When Lollipop came out, the default styling changed for date and time pickers. A common question on the Internet is, how do I change the date and time picker dialog style back to a 'spinner'. While this write-up is primarily in context of use of my plugin in combination with Cordova, the same technique can be applied for other projects/frameworks.
A few years back when I first researched this and attempted to build support for it into the plugin, I went with a kindof hack: using reflection. By setting the android.calendar
property to false, internally some magic was done.
The problem however is that it is not even guaranteed to work. Firstly, reflection can break with newer API levels, but more importantly, not every theme is supported. And this is what causes confusion, it just isn't very reliable - on some devices it works, on others it does not.
So let's do it the proper way!
For this tutorial I am assuming you are using Cordova 8, but it should be similar for other configurations and versions.
-
From the Cordova project root, navigate to the
./res
folder. -
In this folder create a
styles.xml
file. -
As an example let's use this XML and paste it in the
./res/styles.xml
file:<?xml version='1.0' encoding='utf-8'?> <resources> <!-- Declare a new custom main theme. --> <style name="MyAppTheme" parent="android:Theme.DeviceDefault.NoActionBar"> <!-- Reference custom styles that should be active for this theme. --> <item name="android:datePickerStyle">@style/MyDatePickerStyle</item> <item name="android:timePickerStyle">@style/MyTimePickerStyle</item> </style> <!-- Custom date picker styles. --> <style name="MyDatePickerStyle" parent="android:Widget.Material.DatePicker"> <item name="android:datePickerMode">spinner</item> </style> <!-- Custom time picker styles. --> <style name="MyTimePickerStyle" parent="android:Widget.Material.TimePicker"> <item name="android:timePickerMode">spinner</item> </style> </resources>
In this example theme:
- we defined a theme named
MyAppTheme
which we will apply to the Android activity later on. - we defined two custom styles for the date and time picker widget, with an attribute
datePickerMode
andtimePickerMode
both set tospinner
. This should change the pickers from radials into spinners.
-
Open the
config.xml
in the Cordova project root. -
Add the Android schema with a namespace declaration to the
widget
element if it isn't already there:<widget ... xmlns:android="http://schemas.android.com/apk/res/android">
-
Add the following XML to the
widget
element:<widget ...> ... <platform name="android"> <resource-file src="res/styles.xml" target="app/src/main/res/values/styles.xml" /> <edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application/activity"> <activity android:theme="@style/MyAppTheme" /> </edit-config> </platform> ... </widget>
Let's break down what is happening:
The platform
element allows us configure the Android platform specifically, as this does not apply to iOS
or others.
<platform name="android">
</platform>
With the resource-file
element we can copy a file to a target folder during build.
<resource-file src="res/styles.xml" target="app/src/main/res/values/styles.xml" />
The base location of
src
is the project root, whereas thetarget
location points to the location under the platform folder (platforms/android
).NOTE: The
target
location may differ for other Cordova versions.
To enable our custom theme, we replace the default theme with our own on the activity
element:
<edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application/activity">
<activity android:theme="@style/MyAppTheme" />
</edit-config>
After building the project, the
AndroidManifest.xml
should be updated and thestyles.xml
file should be copied, even when completely rebuilding the project from scratch.
Now, when showing the date/time picker, make sure to specify 0
for the android.theme
property to enable the custom theme.
cordova.plugins.DateTimePicker.show({
mode: "datetime",
date: new Date(),
android: {
theme: 0
},
success: function (newDate) {
// handle date
}
})
cordova build android
cordova emulate android
You should now have both pickers in spinner mode.
But wait, what about the original, default radial pickers. Can I still use those too?
Don't worry, just specify one of the built-in themes from R.style.
cordova.plugins.DateTimePicker.show({
mode: "datetime",
date: new Date(),
android: {
theme: 16974126 //Theme_DeviceDefault_Dialog
},
success: function (newDate) {
// handle date
}
})
And the result:
With some extra configuration it is fairly easy to get spinners back in a reliable way and with proper theming.
While in this example I solely focus on changing the picker mode style, there are more styling options available, but I will leave that as an exercise to the reader.