I'm creating a form that consists of EditTexts which launch DatePickerDialogs and TimePickerDialogs.
Here are the sections of the code:
DatePickerDialog
DatePickerDialog datePicker = new DatePickerDialog(context, new DatePickerDialog.OnDateSetListener() {
#Override
public void onDateSet(android.widget.DatePicker view, int chosenYear, int chosenMonth, int chosenDate) {
year = chosenYear;
month = chosenMonth;
date = chosenDate;
set(year, month, date);
}
}, year, month, date);
datePicker.setTitle("Select Date");
datePicker.show();
TimePickerDialog
TimePickerDialog timePicker = new TimePickerDialog(context, new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(android.widget.TimePicker view, int chosenHour, int chosenMinute) {
hour = chosenHour;
minute = chosenMinute;
set(hour, minute);
}
}, hour, minute, false);
timePicker.setTitle("Select Time");
timePicker.show();
Everything works as it should be such as launching the dialogs and setting the date properly. There's this one problem. The previews are not rendered. I don't know why. Hope someone could help. Thanks.
Here are the screenshots:
Notice the white backgrounds.
in your styles.xml add two new styles:
<style name="DatePicker" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#color/your_color</item>
</style>
<style name="TimePicker" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#color/your_color</item>
</style>
Then refer to these styles in your custom theme as followed:
<item name="android:datePickerDialogTheme" tools:targetApi="21">#style/DatePicker</item>
<item name="android:timePickerDialogTheme" tools:targetApi="21">#style/TimePicker</item>
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
I'm seeing an extra space on the right of the DatePickerDialog, only on Android M & N builds. It's not observed on L based build. Here's the screenshot:
Has anyone faced this problem ?
This is the implementation of DatePickerFragment:
public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
public static DatePickerFragment newInstance(int day, int month, int year)
{
DatePickerFragment frag = new DatePickerFragment();
Bundle args = new Bundle();
args.putInt("day", day);
args.putInt("month", month);
args.putInt("year", year);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
int year = getArguments().getInt("year");
int month = getArguments().getInt("month");
int day = getArguments().getInt("day");
DatePickerDialog datePickerDialog =new DatePickerDialog(getActivity(), this, year, month, day);
datePickerDialog.getDatePicker().setMinDate(System.currentTimeMillis() - 1000);
return datePickerDialog;
}
#Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
{
try
{
DatePickerDialogListener listener = (DatePickerDialogListener)getActivity();
listener.onFinishDatePickDialog(year, monthOfYear + 1, dayOfMonth);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
// 1. Defines the listener interface with a method passing back data result.
public interface DatePickerDialogListener {
void onFinishDatePickDialog(int year, int monthOfYear, int dayOfMonth);
}
}
And here's the style sheet which has a component for android:datePickerDialogTheme
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowContentTransitions">true</item>
<item name="colorControlNormal">#color/colorAccent</item>
<item name="colorControlActivated">#color/colorAccent</item>
<item name="colorControlHighlight">#color/colorAccent</item>
<item name="textColorError">#android:color/holo_red_dark</item>
<item name="android:timePickerDialogTheme">#style/AlertDialogCustom</item>
<item name="android:datePickerDialogTheme">#style/AlertDialogCustom</item>
<item name="android:alertDialogTheme">#style/AlertDialogCustom</item>
</style>
<style name="AlertDialogCustom" parent="android:Theme.Material.Light.Dialog.Alert">
<item name="android:colorPrimary">#color/colorPrimary</item>
<item name="android:colorAccent">#color/colorAccent</item>
</style>
NOTE: The issue is not seen if I don't use the styles to modify color.
Do not use Theme.AppCompat.Light.Dialog.Alert, simply use Theme.AppCompat.Light.Dialog is ok. As you look inside,
<style name="Base.ThemeOverlay.AppCompat.Dialog.Alert">
<item name="android:windowMinWidthMajor">#diem/abc_dialog_min_width_major</item>
<item name="andorid:windowMinWidthMinor">#dimen/abc_dialog_min_width_minor</item>
</style>
There is additional size amendment on the style, which turns out is undesired.
I found the fix, it was an issue with my style. I updated the parent to Theme.AppCompat.Light.Dialog.Alert instead of android:Theme.Material.Light.Dialog.Alert and it worked.
Also android:colorAccent has to be changed to colorAccent or else the Calendar Selector color stays Green
Here's what the final style should look like
<style name="AlertDialogCustom" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorAccent">#color/colorAccent</item>
</style>
I'm using a DatePickerDialog in a DialogFragment, which works fine.
I would like to change the colors of:
the background of the action bar
the background of the buttons
the dividers
Here is my DialogFragment:
public class DatePickerDialogFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener
{
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
// init :
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(getActivity(), R.style.DatePickerDialogTest, this, year, month, day);
datePickerDialog.getDatePicker().setBackgroundColor(0xFF500000);
return datePickerDialog;
}
...
}
And here is the style:
<style name="DatePickerDialogTest" parent="Theme.AppCompat.Dialog.Alert">
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:textColorPrimary">#FF00FF00</item>
<item name="colorAccent">#FFFF0000</item>
<item name="android:divider">#android:color/holo_purple</item>
</style>
Every color I use displays properly, except for the backgrounds of the action bar, buttons and dividers.
Is there any way I can easily change those colors?
Thanks.
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.
I am creating a DatePickerDialog that I want to apply a custom theme to. It's only applying part of the custom theme. I asked for no title and a windowBackground that's grey and the resulting entire dialog (except for the numbers and month) is orange. What am I doing wrong? Here is my custom theme:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="GPSTheme" parent="android:style/Theme.Dialog">
<item name="android:textColor">#000000</item>
<item name="android:windowTitleStyle">#style/Theme.Sherlock.Light</item>
<item name="android:background">#drawable/orange_gradient</item>
<item name="android:windowBackground">#drawable/cool_gradient</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
Here is where I am calling the dialog (from within a fragment):
btnStartDate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DatePickerDialog.OnDateSetListener mDateSetListener = new DatePickerDialog.OnDateSetListener() {
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
if (DatesValid(true, year, monthOfYear, dayOfMonth)) {
StartDate.set(Calendar.YEAR, year);
StartDate.set(Calendar.MONTH, monthOfYear);
StartDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
SetTextDates();
} else {
Toast.makeText(
getActivity(),
"Start Date cannot be greater than End Date",
Toast.LENGTH_SHORT).show();
}
GetDistanceTraveledForTime();
}
};
DatePickerDialog d = new DatePickerDialog(getActivity(),
R.style.GPSTheme, mDateSetListener,
StartDate.get(Calendar.YEAR), StartDate
.get(Calendar.MONTH), StartDate
.get(Calendar.DAY_OF_MONTH));
//DatePicker dp = d.getDatePicker();
//LinearLayout l = (LinearLayout)dp.getChildAt(0);
//l.setBackgroundColor(R.drawable.orange_gradient);
d.setIcon(R.drawable.calendar_2_icon);
d.show();
}
});
I looked here: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/themes.xml for all the inherited attributes of Theme.Dialog.
Here is a screen shot: