概要
アプリでユーザから日付を入力してもらうため、次のようにカレンダー(DatePicker)を表示するUIをよく見ます。

今回のブログポストではshowDatePickerを使ってFlutterでDatePickerを表示する方法について説明します。
- showDatePicker: https://api.flutter.dev/flutter/material/showDatePicker.html
ここで紹介するソースコードはGitHubで確認できます。
プロジェクト準備
showDatePickerの使い方を確認するため、次のようにボタンを表示する簡単なアプリを作ってみます。

次のコマンドを実行して新しいFlutterプロジェクトを生成します。
flutter create show_date_picker
新しいFlutterプロジェクトが生成されたら、main.dartファイルを開いて下記のように修正します。
class _MyHomePageState extends State<MyHomePage> {
DateTime date = DateTime.now();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Date Picker Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () {},
child: Text(
"${date.year.toString()}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}",
),
),
),
);
}
}
DatePickerを使ってボタンに表示される日付を変更する予定なので、Statefulウィジェットで生成しました。このようにmain.dartファイルを修正して保存すると、下記のようにボタンがうまく表示されることが確認できます。

今はボタンイベントに何もコードを追加してないので、ボタンを押しても何の動作もしないことが確認できます。
showDatePicker
次は、showDatePickerを使ってDatePickerを表示する方法についてみてみます。ボタンを押した時、showDatePickerを表示するためElevatedButtonウィジェットのonPressed関数を下記のように修正します。
...
ElevatedButton(
onPressed: () async {
final selectedDate = await showDatePicker(
context: context,
initialDate: date,
firstDate: DateTime(2000),
lastDate: DateTime.now(),
);
if (selectedDate != null) {
setState(() {
date = selectedDate;
});
}
},
...,
),
...
showDatePicker関数はFuture<DateTime?>タイプを返すので、async-awaitを使う必要があります。また、ユーザが日付を選択しない場合、nullが帰ってくるので、ユーザが選択した日付を保存するためif文を使いました。最後に、ユーザが選択した日付をsetStateを使ってStateを変更して、画面をアップデートするようにしました。
このようにコードを修正して保存すると、次のようにボタンがまだうまく表示されることが確認できます。

そしたら、ボタンを押してみます。ボタンを押したら以前と違って次のようにカレンダーが表示されることが確認できます。

次はカレンダーで好きな日付を押すと、次のようにボタンの日付がうまく変更されることが確認できます。

initialEntryMode
現在表示されたDatePickerの右上にある修正アイコンを押すと次のように日付を直接入力する画面が確認されます。

この機能を使えないようにするためには、次のようにshowDatePicker関数のinitialEntryModeオプションにDatePickerEntryMode.calendarOnlyを設定する必要があります。
...
ElevatedButton(
onPressed: () async {
final selectedDate = await showDatePicker(
context: context,
initialDate: date,
firstDate: DateTime(2000),
lastDate: DateTime.now(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
);
if (selectedDate != null) {
setState(() {
date = selectedDate;
});
}
},
...,
),
...
そしたら次のように右上に表示された修正アイコンが消えることが確認できます。

多言語
カレンダーに表示される言語を英語ではなく他の言語で表示するためにはflutter_localizationsパッケージをインストールする必要があります。次のコマンドを使ってflutter_localizationsパッケージをインストールします。
flutter pub add flutter_localizations --sdk=flutter
または、pubspec.yamlファイルを次のように修正してflutter_localizationsパッケージをインストールする。
...
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
...
その後、次のようにMaterialAppにlocalizationsDelegatesオプションを追加します。
import 'package:flutter_localizations/flutter_localizations.dart';
...
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
...,
);
}
}
...
その後、showDatePicker関数のlocaleオプションに表示したい言語を設定します。ここでは日本語(Japanese)を設定しました。
...
final selectedDate = await showDatePicker(
context: context,
initialDate: date,
firstDate: DateTime(2000),
lastDate: DateTime.now(),
initialEntryMode: DatePickerEntryMode.calendarOnly,
locale: const Locale('ja', 'JP'),
);
...
このようにコードを修正して保存すると、次のようにカレンダーに表示される言語が英語ではなく日本語がうまく表示されることが確認できます。

テストコード
次のようにテストコードを作成して、showDatePickerがうまく動作するか確認することができます。
...
testWidgets('Change date by DatePicker', (WidgetTester tester) async {
DateTime date = DateTime.now();
await tester.pumpWidget(const MyApp());
final year = date.year.toString();
final month = date.month.toString().padLeft(2, '0');
final day = date.day.toString().padLeft(2, '0');
expect(find.text('$year-$month-$day'), findsOneWidget);
// Press cancel test
await tester.tap(find.text('$year-$month-$day'));
await tester.pump();
await tester.tap(find.text('キャンセル')); // Cancel
await tester.pump();
expect(find.text('$year-$month-$day'), findsOneWidget);
expect(find.text('キャンセル'), findsNothing);
// Change date
await tester.tap(find.text('$year-$month-$day'));
await tester.pump();
await tester.tap(find.text('15'));
await tester.tap(find.text('OK'));
await tester.pump();
expect(find.text("$year-$month-15"), findsOneWidget);
await tester.tap(find.text('$year-$month-15'));
await tester.pump();
await tester.tap(find.text('1'));
await tester.tap(find.text('OK'));
await tester.pump();
expect(find.text("$year-$month-01"), findsOneWidget);
});
...
このテストコードではボタンを押してDatePickerを表示した後、日本語で表示されたキャンセル(キャンセル)ボタンを押して日付の変更をしなくてDatePickerを閉じるテストと実際日付を押して日付を変更するテストを作成してみました。
完了
これでshowDatePickerを使ってFlutterでカレンダーを表示して日付を変更する機能を実装する方法について調べてみました。日付を変更する必要がある場合、日付を直接入力させるより、DatePickerを表示してユーザがもっと楽に日付を変更することができるようにしてみてください。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Dekuが開発したアプリを使ってみてください。Dekuが開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。






