在不同语言环境中,日历的格式是不同的,比如在英语环境中,格式为:MM-dd-YY,而且月份显示的是英文并非数字;中文环境中是YY-MM-dd。如果想要改变可以设置setDisplayedValues()改变英文月份到数字,通过mSpinners.addView()NumberPicker )改变顺序。
String months[] = {"1", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "11", "12"};
FixedHoloDatePickerDialog dlg = new FixedHoloDatePickerDialog(new ContextThemeWrapper(this,android.R.style.Theme_Holo_Light_Dialog_NoActionBar), (view, year, month, dayOfMonth) -> {
yearTv.setText(year + "");
monthTv.setText((month + 1) + "");
dayTv.setText(dayOfMonth + "");
yy = year;
mm = month;
dd = dayOfMonth;
}, yy, mm, dd) {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout mSpinners = findViewById(getContext().getResources().getIdentifier("android:id/pickers", null, null));
if (mSpinners != null) {
NumberPicker mMonthSpinner = findViewById(getResources().getIdentifier("android:id/month", null, null));
NumberPicker mDaySpinner = findViewById(getResources().getIdentifier("android:id/day", null, null));
NumberPicker mYearSpinner = findViewById(getResources().getIdentifier("android:id/year", null, null));
mSpinners.removeAllViews();
if (mYearSpinner != null) {
mSpinners.addView(mYearSpinner);
}
if (mMonthSpinner != null) {
mMonthSpinner.setDisplayedValues(months);
mSpinners.addView(mMonthSpinner);
}
if (mDaySpinner != null) {
mSpinners.addView(mDaySpinner);
}
}
}
@Override
public void onDateChanged(DatePicker view, int year, int month, int day) {
super.onDateChanged(view, year, month, day);
NumberPicker mMonthSpinner = findViewById(getResources().getIdentifier("android:id/month", null, null));
if (mMonthSpinner != null) {
mMonthSpinner.setDisplayedValues(months);
}
}
};
dlg.getDatePicker().setCalendarViewShown(false);
dlg.getDatePicker().setSpinnersShown(true);
dlg.getDatePicker().setMaxDate(System.currentTimeMillis());
dlg.show();
FixedHoloDatePickerDialog 这使用反射来访问私有字段。一般来说,这不是一个强大的方法,你不能指望它。我在这里减轻风险1)将此限制为单个SDK版本,v24; 2)将整个反射代码包裹在一个try {...} catch (Exception e) {/* NOP */}块中,因此如果任何反射失败,则不会发生任何事情,并且将使用(可悲地破坏)默认材料回退。
public class FixedHoloDatePickerDialog extends DatePickerDialog {
public FixedHoloDatePickerDialog(Context context, OnDateSetListener callBack,
int year, int monthOfYear, int dayOfMonth) {
super(context, callBack, year, monthOfYear, dayOfMonth);
// Force spinners on Android 7.0 only (SDK 24).
// Note: I'm using a naked SDK value of 24 here, because I'm
// targeting SDK 23, and Build.VERSION_CODES.N is not available yet.
// But if you target SDK >= 24, you should have it.
if (Build.VERSION.SDK_INT == 24) {
try {
final Field field = this.findField(
DatePickerDialog.class,
DatePicker.class,
"mDatePicker"
);
final DatePicker datePicker = (DatePicker) field.get(this);
final Class> delegateClass = Class.forName(
"android.widget.DatePicker$DatePickerDelegate"
);
final Field delegateField = this.findField(
DatePicker.class,
delegateClass,
"mDelegate"
);
final Object delegate = delegateField.get(datePicker);
final Class> spinnerDelegateClass = Class.forName(
"android.widget.DatePickerSpinnerDelegate"
);
if (delegate.getClass() != spinnerDelegateClass) {
delegateField.set(datePicker, null);
datePicker.removeAllViews();
final Constructor spinnerDelegateConstructor =
spinnerDelegateClass.getDeclaredConstructor(
DatePicker.class,
Context.class,
AttributeSet.class,
int.class,
int.class
);
spinnerDelegateConstructor.setAccessible(true);
final Object spinnerDelegate = spinnerDelegateConstructor.newInstance(
datePicker,
context,
null,
android.R.attr.datePickerStyle,
0
);
delegateField.set(datePicker, spinnerDelegate);
datePicker.init(year, monthOfYear, dayOfMonth, this);
datePicker.setCalendarViewShown(false);
datePicker.setSpinnersShown(true);
}
} catch (Exception e) { /* Do nothing */ }
}
}
/**
* Find Field with expectedName in objectClass. If not found, find first occurrence of
* target fieldClass in objectClass.
*/
private Field findField(Class objectClass, Class fieldClass, String expectedName) {
try {
final Field field = objectClass.getDeclaredField(expectedName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) { /* Ignore */ }
// Search for it if it wasn't found under the expectedName.
for (final Field field : objectClass.getDeclaredFields()) {
if (field.getType() == fieldClass) {
field.setAccessible(true);
return field;
}
}
return null;
}
}
其实如果用DatePicker 通过
android:calendarViewShown="false"
android:spinnersShown="true"
android:datePickerMode="spinner"
也可以做到轻便主题,但是如果想要修改顺序以及英文环境下格式化日期。那么7.0手机就是个坑,因为下面这句话转化英文月份为数字,会报数组越界异常:
String months[] = {"1", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "11", "12"};
...
((NumberPicker) ((ViewGroup) ((ViewGroup) datePicker.getChildAt(0)).getChildAt(0)).getChildAt(0)).setDisplayedValues(months);