カオスな DatePicker のレイアウトのフラグ

属性 API Level
android:calendarViewShown true or false 11
android:spinnersShown true or false 11
android:datePickerMode spinner or calendar 21

datePickerModeは未指定もしくはspinnerがLollipop 未満の表示です。
calendarが Lollipop からの表示になります。

レイアウトの切り替えにフラグが3種類って嫌な予感しかしませんね。

各属性を設定した場合の表示の違い

Theme.AppCompatを指定したFragmentActivityのスクリーンショットです。

DatePickerPattern1 DatePickerPattern2 DatePickerPattern3 DatePickerPattern4 DatePickerPattern5 DatePickerPattern6 DatePickerPattern7 DatePickerPattern8
android:datePickerMode spinner spinner spinner spinner calendar calendar calendar calendar
android:calendarViewShown false false true true false false true true
android:spinnersShown false true false true false true false true
Screenshot DatePickerInFragmentActivity_Spinner_isCalendarViewShown_false_isSpinnersShown_false_Theme_AppCompat.png DatePickerInFragmentActivity_Spinner_isCalendarViewShown_false_isSpinnersShown_true_Theme_AppCompat.png DatePickerInFragmentActivity_Spinner_isCalendarViewShown_true_isSpinnersShown_false_Theme_AppCompat.png DatePickerInFragmentActivity_Spinner_isCalendarViewShown_true_isSpinnersShown_true_Theme_AppCompat.png DatePickerInFragmentActivity_Calendar_isCalendarViewShown_false_isSpinnersShown_false_Theme_AppCompat.png DatePickerInFragmentActivity_Calendar_isCalendarViewShown_false_isSpinnersShown_true_Theme_AppCompat.png DatePickerInFragmentActivity_Calendar_isCalendarViewShown_true_isSpinnersShown_false_Theme_AppCompat.png DatePickerInFragmentActivity_Calendar_isCalendarViewShown_true_isSpinnersShown_true_Theme_AppCompat.png

DatePickerPattern1-4 は Lollipop 未満の表示です。
DatePickerPattern5-8 はandroid:datePickerMode="calendar"calendarViewShownspinnersShownより強いので全て Lollipop のカレンダー表示になっています。

どうしてこうなった

そもそも bool で定義すべきではない表示形式を calendarViewShownspinnersShown の2種類の bool で表してしまったことが全ての元凶です。 本来は3種類のレイアウトを2種類の bool で表現したため、4種類の状態が表現できるようになってしました。 そこに calendarViewShownspinnersShown よりも強い datePickerMode が追加されカオスな状況になりました。

どうすべきだったのか

calendarViewShownspinnersShownの両方にfalseを指定した際に
何も表示しない状態がある時点で怪しいと思わなければならないと思います。
Lollipop 未満の時点で表示形式は以下のようなenumで定義したほうが良かったと思います。

enum DatePickerMode {
    spinenr,
    calendar,
    spinner_and_calendar
}

そうすれば DatePickerPattern1 のような何も表示されない状態もなく、
Lollipop で追加された表示形式も、テーマ次第でcalendarなどの表示を変えてしまうとか
materialとか何とかをenumの値に追加するだけで済んだと思います。

まとめ

怪しいフラグを増やしそうになったら抽象化して考えてboolが適切か考えましょう。

リポジトリ

wada811/Android-DatePicker-Sample