Reputation: 73
I'm trying to change the date picker style to spinner for one date picker, others shall remain default.
I've tried:
public static class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener {
private int style;
DatePickerFragment(int xml) {
style = xml;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Calendar c = Calendar.getInstance();
final DatePickerDialog datePickerDialog = new DatePickerDialog(getActivity(), this, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
LayoutInflater inflater = requireActivity().getLayoutInflater();
datePickerDialog.setView(inflater.inflate(style, null));
return datePickerDialog;
}
@Override
public void onDateSet(DatePicker view, int year, int month, int day) {
Log.i("DatePicker", "received date from picker: " + day + "." + month + "." + year);
}
}
with style XML:
<?xml version="1.0" encoding="utf-8"?>
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:datePickerMode="spinner"
android:calendarViewShown="false" />
but whenever I enter a date in the spinner and hit OK, the current (todays) date is logged in the onDateSet
method and not the chosen one in the date picker.
I also tried to overwrite the OK button with:
datePickerDialog.setButton(DialogInterface.BUTTON_POSITIVE, "asd", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.i("DatePicker", "received date from picker2: " + datePickerDialog.getDatePicker().getDayOfMonth() + "." + datePickerDialog.getDatePicker().getMonth()+1 + "." + datePickerDialog.getDatePicker().getYear());
}
});
but without change.
From my understanding and the behavior, I'm creating some overlay with inflater.inflate(style, null)
where I select the date, but the overlay values are not populated.
How can I use the inflater to change the date picker style?
Note...I can't:
Thanks!
Upvotes: 4
Views: 4751
Reputation: 14203
Root cause: DatePickerDialog class has a final field named mDatePicker
, this field is initialized once inside the constructor, so when you call.
final DatePickerDialog datePickerDialog = new DatePickerDialog(getActivity(), this, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
From that point, the mDatePicker
field cannot be re-assigned to any value because its modify is final
. When you call setView
on the dialog, it just changes the view of the dialog without knowing the datePicker
inside your custom layout.
That explains why when you change the date on the custom layout and hit OK button, it collects the value of mDatePicker
to return your fragment instead of datePicker
in your custom layout.
Solution 1: Using a custom style to change the date picker mode to spinner, but requires min API 21
Step 1: Define a style in styles.xml file
<style name="customDatePickerStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="android:datePickerStyle">@style/customDatePicker</item>
</style>
<style name="customDatePicker" parent="@android:style/Widget.Material.Light.DatePicker">
<item name="android:datePickerMode">spinner</item>
<item name="android:calendarViewShown">false</item>
</style>
Step 2: In DatePickerFragment class
public class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Calendar calendar = Calendar.getInstance();
return new DatePickerDialog(requireActivity(),
R.style.customDatePickerStyle,
this,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH));
}
@Override
public void onDateSet(DatePicker view, int year, int month, int day) {
Log.i("DatePicker", "received date from picker: " + day + "." + month + "." + year);
}
}
Solution 2: Create own custom date picker fragment by using a custom layout file, work for all APIs
public class DatePickerFragment extends DialogFragment
implements DialogInterface.OnClickListener {
private int style;
private DatePicker mDatePicker;
DatePickerFragment(int xml) {
style = xml;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View view = requireActivity().getLayoutInflater().inflate(style, null);
Calendar calendar = Calendar.getInstance();
mDatePicker = view.findViewById(R.id.datePicker);
mDatePicker.init(calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH),
null);
return new AlertDialog.Builder(requireActivity())
.setView(view)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this)
.create();
}
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
mDatePicker.clearFocus();
onDateSet(mDatePicker,
mDatePicker.getYear(),
mDatePicker.getMonth(),
mDatePicker.getDayOfMonth());
break;
case DialogInterface.BUTTON_NEGATIVE:
dialog.dismiss();
break;
}
}
public void onDateSet(DatePicker view, int year, int month, int day) {
Log.i("DatePicker", "received date from picker: " + day + "." + month + "." + year);
}
}
Upvotes: 2