お客様の要望から、すべてのAndroid OSバージョン、次のように、DatePickerDialogでHOLOスタイルを維持したいと考えています: DatePicker on Android 7-
しかし、Android 7:では正しく機能しないようです。
私の実装から:
new DatePickerDialog(getContext(), AlertDialog.THEME_HOLO_LIGHT,
mCalendarPickerListener,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH));
以前のAndroid 7.)では問題なく動作しています。
編集:ソリューションはAPI 25で修正されていることが判明 https://code.google.com/u/106133255289400340786/
DatePickerDialog
を使用して、ユーザーに誕生日のプロンプトを表示します。残念ながら、試してみると、マテリアルをテーマにしたダイアログについてユーザーから多くの苦情が寄せられたため、それに切り替えることはできません。ホロをテーマにしたダイアログに固執する必要があります。
Android 7.0にはバグが付属しています:このプラットフォームでHoloテーマを使用しようとすると、代わりに壊れたマテリアルテーマの使用にフォールバックします。 DatePickerDialog
の場合。次の2つのバグレポートを参照してください。
Jeff Lockhartによるこの回避策 の修正された形式を使用しました。これらのバグレポートで参照されています。
_private static final class FixedHoloDatePickerDialog extends DatePickerDialog {
private 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 mDatePicker
_フィールドを取得しますDatePickerDelegate mDelegate
_フィールドを取得しますDatePickerSpinnerDelegate
(必要なデリゲートのタイプ)のインスタンスではないことを確認しますDatePicker
からすべてのビューを削除します。これらはマテリアルカレンダーウィジェットであるため、DatePickerSpinnerDelegate
の新しいインスタンスを作成し、それをこのダイアログのmDelegate
のmDatePicker
フィールドに割り当てます。mDatePicker
を再初期化し、スピナーを膨らませますこの回避策を使用するには、ContextThemeWrapper
の周りにContext
を作成します。これにより、テーマ(この場合はHolo)を設定できます。
_final Context themedContext = new ContextThemeWrapper(
this.getContext(),
Android.R.style.Theme_Holo_Light_Dialog
);
final DatePickerDialog dialog = new FixedHoloDatePickerDialog(
themedContext,
datePickerListener,
calender.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
_
メモ:
try {...} catch (Exception e) {/* NOP */}
ブロックでラップするため、リフレクションのいずれかが失敗しても何も起こらず、(悲しいことに壊れた)デフォルトのマテリアルフォールバックが使用されます。TimePickerDialog
用でした。代わりにDatePickerDialog
で動作するように変更し、ソリューションを単純化して一般的ではなく、正確なユースケースに固有のものにしました。ただし、より完全な元のバージョンを使用して、Date
の代わりにTime
用に微調整することもできます。日付ピッカーには独自のスタイルがあります https://developer.Android.com/reference/Android/R.style.html#Widget_DatePicker
R.style.Widget.Holo.DatePicker
の代わりにAlertDialog.THEME_HOLO_LIGHT
が必要だと思います。親として@Android:style/Widget.Holo.DatePicker
を持つ独自の空のスタイルを作成し、それを使用する必要がある可能性があります。
savantoによるソリューション に加えて:API 28以降、Holo LightThemeは非推奨になりました。 API 21/Lollipopデバイス以降を対象とする場合は、マテリアルデザインスタイルを使用する必要があります。 このソリューション を確認してください。これらのスタイルを定義してから、ContextThemeWrapper
のR.style.dlg_datePicker
にリンクしました。
<style name="dlg_datePicker" parent="Theme.AppCompat.Light.Dialog">
<item name="Android:datePickerStyle">@style/datePicker_style</item>
<item name="Android:textSize">18sp</item>
</style>
<style name="datePicker_style" parent="Android:Widget.Material.Light.DatePicker">
<item name="Android:datePickerMode">spinner</item>
</style>
それが機能していることをフォローしてみてください。私はテストしました。そして、それは空白のギャップを持っていません。
また、mDatePickerListener
は、作成できる私のDatePickerListnerです。
//Setting theme to Android.R.style.Theme_Holo_Light_Dialog
Calendar cal = Calendar.getInstance(TimeZone.getDefault());
DatePickerDialog datePicker = new DatePickerDialog(getContext(), Android.R.style.Theme_Holo_Light_Dialog,
mDatePickerListener,
cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH),
cal.get(Calendar.DAY_OF_MONTH));
datePicker.setCancelable(false);
datePicker.setTitle(getString(R.string.select_your_dob));
//This line is important to remove blank gaps
datePicker.getWindow().setBackgroundDrawable(new ColorDrawable(Android.graphics.Color.TRANSPARENT));
datePicker.show();