成果物
やりたいこと
DatePickerの背景に画像を設定したい。
興味本位です。
課題
- 標準のDatePickerは単色しか設定できない
- 背景に画像を設定できるDatePickerのパッケージ(無料)はない
ということで自作しました。
大まかな流れ
① DatePickerの背景を透過にする
② StackでDatePickerの後ろにImageを置く
③ 細かい調整
① DatePickerの背景を透過にする
基本的にはshowDatePicker()
でDatePickerを表示すると思います。
その引数のbuilder: (context, child) => Widget
を使ってThemeを設定することで、DatePickerの色などをカスタマイズできます。
こんな感じです。
Theme(
data: Theme.of(context).copyWith(
datePickerTheme: DatePickerTheme.of(context).copyWith(...),
textButtonTheme: TextButtonThemeData(...),
),
child: child,
)
今回はこのようにしてDatePickerの背景を透過させます。
datePickerTheme: DatePickerTheme.of(context).copyWith(
backgroundColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
),
surfaceTintColor
もtransparent
に設定しないと若干色味が変わるので設定してください。
こんな感じです。
transparent | null |
---|---|
|
② StackでDatePickerの後ろにImageを置く
背景が透過のDatePickerを表示できたら、画像を設定します。
標準のDatePickerは角丸になっているので、ClipRRect
で囲ったImageウィジェットを使います。
ClipRRect(
borderRadius: BorderRadius.circular(32),
child: Image.asset(...)
)
Stack
で画像を背面、`DatePickerDialogを前面にします。
Stack(
alignment: AlignmentDirectional.center,
children: [
ClipRRect(
child: Image.asset(...),
),
Theme(
data: Theme.of(context).copyWith(
datePickerTheme: DatePickerTheme.of(context).copyWith(
backgroundColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
),
),
child: datePickerDialog
)
]
)
画像のサイズは下記のものを用意すると標準のDatePickerのサイズの比率と同じになって綺麗におさまります。
MaterialDesign3を使用している場合は、 幅328, 高さ512 の比率の画像
MaterialDesign2を使用している場合は、 幅330, 高さ518 の比率の画像
③ 細かい調整
以下DatePickerの他の部分の色設定
Theme(
data: Theme.of(context).copyWith(
datePickerTheme: DatePickerTheme.of(context).copyWith(
backgroundColor: // 背景色
surfaceTintColor: // 表面にかかる色
dividerColor: // ヘッダーとカレンダーの間の色
todayForegroundColor: // 今日の文字色
todayBackgroundColor: // 今日の背景色
dayBackgroundColor: // 日付の背景色
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(foregroundColor: // Cancel, OKボタンの文字色),
),
),
child: child,
),
日付の背景色について、選択したものだけ別の色にするためにはこのようにします。
dayBackgroundColor: MaterialStateProperty.resolveWith((states) {
if (states.contains(MaterialState.selected)) {
return Colors.green;
}
return Colors.transparent;
}),
今回使った画像