I am setting the datePickerMode in my styles file to spinner like this:
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:dialogTheme">#style/MyDialogTheme</item>
<item name="android:datePickerStyle">#style/MyDatePicker</item>
</style>
<style name="ItvDialogTheme" parent="android:Theme.Material.Light.Dialog">
<item name="android:datePickerStyle">#style/MyDatePicker</item>
</style>
<style name="MyDatePicker" parent="android:Widget.Material.Light.DatePicker">
<item name="android:datePickerMode">spinner</item>
</style>
and then create a DatePicker
DatePickerDialog.OnDateSetListener onDateSetListener = new DatePickerDialog.OnDateSetListener() {
#Override
public void onDateSet(final DatePicker view, final int year, final int monthOfYear, final int dayOfMonth) {
//handle result
}
};
DatePickerDialog dialog = new DatePickerDialog(this, onDateSetListener, dob.getYear(), dob.getMonth() - 1,
dob.getDay());
dialog.show();
This worked fine across a lot of devices including the Samsung Galaxy S7 Edge on Android 6, but since updating the device to Android 7 it ignores the mode spinner and shows the calendar.
The spinner works fine on an One Plus 3 on Android 7.1.1.
Any ideas?
You may be running into this issue (#37120178) datepicker dialog can't switch to spinner on Android 7.0 device. If so, there is a work-around documented on that page. I haven't tried the work-around, but it may be worth a shot. (See below for implementation of the work-around.)
By the way, I have a Samsung S7 (not an edge) running 7.0. I can get a DatePicker spinner if I define it in XML, so another work-around would be to define the DatePicker spinner in XML and use it in the dialog.
Here is a gist of this solution.
Odd, but those fixes in the bug report seem to be for the time picker although the report is for the date picker. I dug around a bit and found Use DatePicker spinners in API 24 as a potential fix. Again, I have not tried this.
This reflection logic does appear to work. It showed the spinner beside the calendar view for me. If you want just the spinner, you will need to add the following to your style:
<item name="android:calendarViewShown">false</item>
(Credit for this work-around goes to lognaturel and jeffdgr8).
Here is what my custom DatePickerDialog looks like with the reflection logic:
public class MyReflectionDatePickerDialog extends DatePickerDialog {
private DatePicker mDatePicker;
#RequiresApi(api = Build.VERSION_CODES.N)
public MyReflectionDatePickerDialog(#NonNull Context context, #Nullable OnDateSetListener listener,
int year, int month, int dayOfMonth) {
super(context, listener, year, month, dayOfMonth);
fixSpinner(context, year, month, dayOfMonth);
}
// include gist here from:
// https://gist.github.com/lognaturel/232395ee1079ff9e4b1b8e7096c3afaf
}
You would instantiate this custom view as shown below:
DatePickerDialog dialog;
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) {
dialog = new MyDatePickerDialog(this, onDateSetListener, dob.getYear(),
dob.getMonth() - 1, dob.getDay());
} else {
dialog = new DatePickerDialog(this, onDateSetListener, dob.getYear(),
dob.getMonth() - 1, dob.getDay());
}
You can try this.
datePicker.setCalendarViewShown(false);
You Should try to raise the
targetSdkVersion to 24 because of the android 7.0
Related
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:
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:
(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:
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?
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
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! :)
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.
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
Seems like anyone using Marshmallow (Android 6.0) is not able to use the DatePicketDialog within my app. There appears to be some sort of theme issue that I'm encountering. I use a DialogFragment which contains a DatePicketDialog for the user to select birthday. Here are shots of the DialogFragment with Android 5.x an d 6.x.
I attempted to add a theme in the DatePickerDialog constructor, but that made the DialogFragment fullscreen and I don't want that. Does anyone know how I can get the DatePickerDialog to look like it was prior to Marshmallow?
UPDATE 1
Here is the code where I create the DialogFragment:
DialogFragment ageFragment = new DatePickerDialogFragment();
ageFragment.show(getFragmentManager(), "datePicker");
Here is the onCreateDialog inside the DatePickerDialogFragment:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the current date as the default date in the picker if no filters are set
Calendar cal = Calendar.getInstance();
// Set the date 18 years previous, since only 18 and older are allowed on the app
cal.add(Calendar.YEAR, -18);
int year, month, day;
if (iDialogListener.getYear() == -1 || iDialogListener.getMonth() == -1
|| iDialogListener.getDay() == -1) {
Calendar defaultCal = Calendar.getInstance();
// 40 is the default age to show
defaultCal.add(Calendar.YEAR, -40);
year = defaultCal.get(Calendar.YEAR);
month = defaultCal.get(Calendar.MONTH);
day = defaultCal.get(Calendar.DAY_OF_MONTH);
} else {
year = iDialogListener.getYear();
month = iDialogListener.getMonth();
day = iDialogListener.getDay();
}
DatePickerDialog datepicker = new DatePickerDialog(getActivity(), this, year, month, day);
datepicker.getDatePicker().setMaxDate(cal.getTimeInMillis());
Calendar minDate = Calendar.getInstance();
minDate.set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR) - 100);
datepicker.getDatePicker().setMinDate(minDate.getTimeInMillis());
// Create a new instance of DatePickerDialog and return it
return datepicker;
}
In the themes.xml the only line that touches Dialogs is
<item name="android:alertDialogTheme">#style/CustomDialogTheme</item>
But if I'm thinking right, that doesn't touch the DialogFragment does it?
Update 2
Here is the CustomDialogTheme:
<style name="CustomDialogTheme" parent="#android:style/Theme.Holo.Light.Dialog">
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowMinWidthMajor">#android:dimen/dialog_min_width_major</item>
<item name="android:windowMinWidthMinor">#android:dimen/dialog_min_width_minor</item>
</style>
You create theme in styles.xml but didn't refer it to DatePickerDialog like
DatePickerDialog dlg = new DatePickerDialog(getActivity(),
R.style.datepickerCustom,this,year,month,day);
and create a folder name values-v21 and add a copy of style.xml to it. and paste
<style name="datepickerCustom" parent="#android:style/Theme.DeviceDefault.Light.Dialog">
<item name="android:colorAccent">#color/orange_theme</item>
<item name="android:windowBackground">#android:color/darker_gray</item>
<!--<item name="android:windowContentOverlay">#null</item>-->
<!--<item name="android:textColorPrimary">#color/white</item>-->
<!--<item name="android:textColorSecondary">#color/white</item>-->
</style>
Just change colorAscent color in styles.xml :
<style name="MyMaterialTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorAccent">#FC6C2D</item> ---> I used orange color here to display the picker dialog in orange color for marshmallow device.
<item name="android:textColorPrimary">#000000</item>
<item name="android:textColorSecondary">#000000</item>
</style>
Thanks to the post How to change the style of Date picker in android?, I was able to properly show the DatePicker. I had to use parent="Theme.AppCompat.Light.Dialog" when styling the DatePicker
I am using the following code to display a datepicker dialog:
DatePickerDialog dialog = new DatePickerDialog(getActivity(), new DatePickerDialog.OnDateSetListener()
{
#Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
{
mDateOfJourney.set(year, monthOfYear, dayOfMonth);
if (mDateOfJourney.after(mCalendar) || mDateOfJourney.equals(mCalendar))
{
setJourneyDateView(mDateOfJourney);
} else {
Toast.makeText(getActivity(), getString(R.string.invalid_date), Toast.LENGTH_SHORT).show();
}
}
}, mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH));
dialog.getDatePicker().setMinDate(mCalendar.getTimeInMillis());
dialog.show();
The output of this code has some rendering issues: It shows up like this:
In the picture above, the window's background is null. Look through your app's style definition. You might find this somewhere:
<item name="android:windowBackground">#null</item>
Or else, you might have set the window's background to null: getWindow().setBackgroundDrawable(null).
The only theme I know that sets this attribute for you is Theme.NoDisplay. So, if you're not using this theme as a base (or as is), you will have to use a different theme.
I wanted to show a DatePicker in a DialogFragment:
public class DatePickerDialogFragment extends DialogFragment {
private OnDateSetListener dateSetListener = null;
private String title = null;
public DatePickerDialogFragment() {}
public DatePickerDialogFragment(OnDateSetListener dateSetListener, String title) {
this.dateSetListener = dateSetListener;
this.title = title;
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(this.getActivity(), this.dateSetListener, year, month, day);
datePickerDialog.getDatePicker().setCalendarViewShown(false);
datePickerDialog.setTitle(this.title);
return datePickerDialog;
}
}
Unfortunately datePickerDialog.getDatePicker().setCalendarViewShown(false); is completly ignored. I hate the calendar view because it is ugly and uncomfortable. So how can i disable it?
In my "values-v21/styles.xml" I've modified activity theme as below it's hiding calendar & shows simple datepicker spinner. You might want to use a drawable with white background & rounded corners:
<item name="android:datePickerDialogTheme">#style/style_date_picker_dialog</item>
</style>
<style name="style_date_picker_dialog" parent="#android:style/Theme.DeviceDefault.Light">
<item name="android:windowIsFloating">true</item>
<item name="android:windowBackground">#drawable/dialog_background</item>
<item name="android:datePickerStyle">#style/style_datepicker</item>
</style>
<style name="style_datepicker" parent="android:Widget.Material.Light.DatePicker">
<item name="android:datePickerMode">spinner</item>
</style>
This has been answered elsewhere: Android Material Design Inline Datepicker issue, and trying to solve it with the accepted answer got me no where.
Basically you need to do:
<DatePicker
...
android:datePickerMode="spinner" />
because setCalandarShown(); has been deprecated.
How is it possible to get a DatePickerDialog with Holo Light theme?
When creating a DatePickerDialog as follows:
DatePickerDialog dpd = new DatePickerDialog(new ContextThemeWrapper(this,
android.R.style.Theme_Holo_Light_Dialog_NoActionBar),
new DateListener(v), mTime.year, mTime.month, mTime.monthDay);
or with theme android.R.style.Theme_Holo_Light or android.R.style.Theme_Holo_Light_Dialog, I get a date picker with a standard title and standard buttons. I tried to use a custom theme with a holo light parent too, but it didn't work either. It seems to work with theme android.R.style.Theme_Holo, but the result is a dark background (as expected), but I would like to have a light one.
The application's android.jar is of version 14, the application is running on a divice with android version 3.2.
I have seen an example here: http://as400samplecode.blogspot.com/2011/10/android-datepickerdialog.html, which shows a DatePickerDialog with the holo light theme, the way I would like to have it. I don't know why it doesn't work with my setup.
Thank you for help.
The DatePickerDialog has a constructor which accepts a theme
DatePickerDialog(Context context, int theme, DatePickerDialog.OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth)
just update your code to include the style you want without the need for a ContextThemeWrapper
DatePickerDialog dpd = new DatePickerDialog(this,
android.R.style.Theme_Holo_Light_Dialog_NoActionBar,
new DateListener(v), mTime.year, mTime.month, mTime.monthDay);
It's working for me that way.
Read this Android DatePickerDialog example code which includes how to use different Themes in DatePickerDialog.
Here is the such one.
DatePickerDialog Constructor which support to define Theme.
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);
return new DatePickerDialog(getActivity(), AlertDialog.THEME_HOLO_DARK, this, year, month, day);
For Material style this worked for me:
int datePickerThemeResId = 0;
if (android.os.Build.VERSION.SDK_INT >= 21) {
datePickerThemeResId = android.R.style.Theme_Material_Light_Dialog;
}
new DatePickerDialog(
context,
datePickerThemeResId,
(view, year, month, dayOfMonth) -> {},
year,
month,
day
).show();