DatePickerDemoForAndroid24
解决 DatePickerDialog 在 Android7.0 API24 上使用AlertDialog.THEME_TRADITIONAL
、AlertDialog.THEME_HOLO_DARK
、AlertDialog.THEME_HOLO_LIGHT
等样式时无法显示为 Spinner 样式的问题。
完整项目与演示地址
API24 无法显示 Spinner 样式
在设备 API24 时,调用DatePickerDialog
来选择日期和时间时,如果指定的主题为THEME_TRADITIONAL
、THEME_HOLO_DARK
或THEME_HOLO_LIGHT
,会出现和其他 API Level 不一样的对话框。
-
THEME_TRADITIONAL
-
THEME_HOLO_DARK
-
THEME_HOLO_LIGHT
解决方式
在Build.VERSION.SDK_INT == 24
时做特殊处理,传入对应 theme 的 ContextThemeWrapper,使用 DatePickerDialogForAndroid24 来展示 Spinner 样式的 DatePickerDialog。
/**
* Api24下显示Spinner样式的Dialog
* @param theme ContextThemeWrapper的theme与DialogTheme的对应关系如下
* android.R.style.Theme_Dialog -> AlertDialog.THEME_TRADITIONAL
* android.R.style.Theme_Holo -> AlertDialog.THEME_HOLO_DARK
* android.R.style.Theme_Holo_Light -> AlertDialog.THEME_HOLO_LIGHT
*/
private fun showDatePickerDialogApi24(theme: Int) {
val themeContext =
ContextThemeWrapper(this@MainActivity, theme)
try {
val dialog = DatePickerDialogForAndroid24(
themeContext,
null,
Calendar.getInstance().get(Calendar.YEAR),
Calendar.getInstance().get(Calendar.MONTH),
Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
)
dialog.create()
dialog.getButton(DialogInterface.BUTTON_NEGATIVE).visibility = View.GONE
dialog.show()
} catch (e: Exception) {
showAlertDialog(e.toString())
e.printStackTrace()
}
}
class DatePickerDialogForAndroid24(
context: Context,
listener: OnDateSetListener?,
year: Int,
monthOfYear: Int,
dayOfMonth: Int
) : DatePickerDialog(context, listener, year, monthOfYear, dayOfMonth) {
init {
if (Build.VERSION.SDK_INT == 24) {
try {
val field = findField(
DatePickerDialog::class.java,
DatePicker::class.java,
"mDatePicker"
)
val datePicker = field.get(this) as DatePicker
val delegateClass =
Class.forName("android.widget.DatePicker\$DatePickerDelegate")
val delegateField = findField(DatePicker::class.java, delegateClass, "mDelegate")
val delegate = delegateField.get(datePicker)
val spinnerDelegateClass = Class.forName("android.widget.DatePickerSpinnerDelegate")
if (delegate.javaClass != spinnerDelegateClass) {
delegateField.set(datePicker, null)
datePicker.removeAllViews()
val spinnerDelegateConstructor = spinnerDelegateClass.getDeclaredConstructor(
DatePicker::class.java,
Context::class.java,
AttributeSet::class.java,
Int::class.java,
Int::class.java
)
spinnerDelegateConstructor.isAccessible = true
val spinnerDelegate = spinnerDelegateConstructor.newInstance(
datePicker,
context,
null,
android.R.attr.datePickerStyle,
0
)
delegateField.set(datePicker, spinnerDelegate)
datePicker.init(year, monthOfYear, dayOfMonth, this)
datePicker.calendarViewShown = false
datePicker.spinnersShown = true
}
} catch (e: Exception) {
e.printStackTrace()
}
}
else{
throw Exception("Not Android 7.0 Device")
}
}
}
完整演示
- API24
- API30