フロント側をFlutter(スマホ)Thymeleaf(PC)、バックエンド側SpringBootの自動作成勉強中
9:45
①今日は、Flutterでの日付のダイヤログ入力を調査する。(ダイヤログ画面じゃないと、共通的に使う時、使い勝手がわるいので)
まずはtable_calendarとintlパッケージをインストールした。
pubspec.yamlに
dependencies: flutter: sdk: flutter table_calendar: ^3.0.5 intl: ^0.17.0
を追加して、pub getを実行。
20:18
①まだまだ、だけど、こんなところまででできた。
途中、
②Locale data has not been initialized, call initializeDateFormatting(
更にimportを「import 'package:intl/date_symbol_data_local.dart'; 」にしないといけない。
③日付ダイアログはできたが、日を押してもその日に色がつかない。理由は、setStateが使えないからだった。
そこで、NETで調べた。結果、以下を修正して動いた。
・SimpleDialogクラスがStatelessWidgetであるため、setStateできていないようです。
・StatelessWidgetをStatefulWidgetとして扱うためには、『StatefulBuilder』ウィジェットを使うらしい。
20:55
①ここで、今できている画面遷移を載せておこう。詳細は明日また考えるとして。
テストとして日付項目を作ってテストした。
日付選択ボタン押下で、日付のダイヤログ画面を表示する。
2020年1月を表示して、1月1日に赤丸”祝"がついている(イベントを使って表示している)ことを確認した。
さらに、1月7日を選択して色がつくことを確認した。
OK押下で選択した1月7日が反映したことを確認した。
②Flutterプログラム
■画面.dartに以下を追加した
String _focusedDayStr=""; //--テスト日付入力 start---------------------------- contentWidgets.add( Row ( // mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ // テスト日付の入力フォーム Container( margin: const EdgeInsets.fromLTRB(10.0, 0, 10.0, 5), padding: const EdgeInsets.fromLTRB(10.0, 0, 10.0, 0), child:Text(_focusedDayStr, textAlign: TextAlign.left, overflow: TextOverflow.clip, ), ), Container( margin: const EdgeInsets.fromLTRB(5, 0, 5, 5), padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), child: ElevatedButton( onPressed: () async { String? _str = await CommUtils.openDateDialogComm(context, '日付選択', DateTime.now()); if (_str != Consts.cancel) { setState(() { _focusedDayStr = _str!; }); } }, style: ElevatedButton.styleFrom( primary: Colors.blue, ), child: const Text("日付選択"), ), ), ] ), ); //--テスト日付入力 end----------------------------
■CommUtilsクラスに以下を追加した
/// 日付入力ダイヤログ /// 選択日付、CANCELを戻す。 static Future<String?> openDateDialogComm(BuildContext context, String msg, DateTime _focusedDay) async { initializeDateFormatting('ja', null); DateFormat outputFormat = DateFormat('yyyy/MM/dd'); DateTime? _selectedDay; // 祝祭日リスト Map<DateTime, List> _eventsList = { DateTime(2022, 1, 1, 0, 0): ['祝'], }; int getHashCode(DateTime key) { return key.day * 1000000 + key.month * 10000 + key.year; } // TableCalendarでは、カレンダーに読み込むイベントをMapで定義した場合、 // LinkedHashMap使用が推奨されている。 final _events = LinkedHashMap<DateTime, List>( equals: isSameDay, hashCode: getHashCode, )..addAll(_eventsList); List getEventForDay(DateTime day) { return _events[day] ?? []; } var result = await showDialog<String>( context: context, barrierDismissible: false, builder: (BuildContext context) { return StatefulBuilder( builder: (context, setState) { return SimpleDialog( title: Text(msg), children: <Widget>[ TableCalendar( locale: 'ja', // カレンダーの最初と最後の月を設定 firstDay: DateTime.utc(1950, 1, 1), lastDay: DateTime.utc(2050, 12, 31), // focusedDayによって日付に印がつく focusedDay: _focusedDay, // イベントを読み込む。祝日に赤丸”祝”を表示 eventLoader: getEventForDay, // カレンダーフォーマットを月単位とする calendarFormat: CalendarFormat.month, // カレンダーフォーマット変更ボタンを表示しない headerStyle: const HeaderStyle( formatButtonVisible: false, ), // どの日が現在選択されているかを判断する。 // dayが選択されたら、trueを返す。 selectedDayPredicate: (day) { return isSameDay(_selectedDay, day); }, // 選択した日付を一時的に保存し、selectedDayPredicateオプションで // 保存された日付情報にフォーカスを当てて印が付けている。 onDaySelected: (selectedDay, focusedDay) { if (!isSameDay(_selectedDay, selectedDay)) { setState(() { _selectedDay = selectedDay; _focusedDay = focusedDay; }); } }, onPageChanged: (focusedDay) { _focusedDay = focusedDay; }, calendarBuilders: CalendarBuilders( // イベントマーカーをmarkerBuilderを使用してカスタマイズする markerBuilder: (context, date, events) { if (events.isNotEmpty) { return _buildEventsMarker(date, events); } }, ), ), SimpleDialogOption(child: const Text('OK'), onPressed: () { // 選択した日付を戻す Navigator.pop(context, _selectedDay==null?Consts.cancel:outputFormat.format(_selectedDay!)); },), SimpleDialogOption(child: const Text('キャンセル'), onPressed: () { // ”cancel”を戻す Navigator.pop(context, Consts.cancel); },) ], ); } ); }, ); return result; } // 日付入力ダイヤログ // イベントマーカーを赤丸”祝”とする static Widget _buildEventsMarker(DateTime date, List events) { return Positioned( right: 5, bottom: 5, child: AnimatedContainer( duration: const Duration(milliseconds: 300), decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.red[300], ), width: 16.0, height: 16.0, child: Center( child: Text( '祝', style: const TextStyle().copyWith( color: Colors.white, fontSize: 12.0, ), ), ), ), ); }
■2022/06/15に、勉強した成果:『Flutter_JavaSpringプログラム自動作成◎自動生成ツール』をVectorに載せました。Zenn本も書きました。使ってみての感想や間違いの指定や、こうやったほうがいいとかの情報があればメールください。
・Vector
www.vector.co.jp
・Zenn本(Flutter_JavaSpringプログラム自動作成)
zenn.dev