【Flutter】FlutterHooks×Calendarを使用した状態管理について

Flutter状態管理

table_calendarを使ったアプリにFlutter Hooksを実装することでHooksの理解を深めたく取り組んでみました。

備忘録としてここに記載します。どなた参考になれば幸いです。

実装時の各バージョン

Flutter 3.0.5 
Framework • revision f1875d570e (9 months ago) • 2022-07-13 11:24:16 -0700
Engine • revision e85ea0e79c
Tools • Dart 2.17.6 • DevTools 2.12.2
  table_calendar: ^3.0.9
  flutter_hooks: ^0.18.6

完成図

今回はカレンダーフォーマットを変える部分をuseStateを使用して実装する簡単なものになります。
画面下のBottomNavigaitonBarの解説についてはしていないので詳しくは下記を参考にしてください。

HookWidgetで作成

Flutter Hooksを使用するためにカレンダーのページはHookWidgetを使用します。

class CalenderPage extends HookWidget {
   CalenderPage({Key? key}) : super(key: key);

useStateを宣言

今回は初期値が0のuseStateをformatIndexという変数を設定しています。
(変数名ビミョーですみませんmm)

  Widget build(BuildContext context) {
    final formatIndex = useState(0);

カレンダーフォーマットの配列を宣言

実際に選択された際のカレンダーフォーマットを配列のインデックス(何番目か)によって変更できるようにするために_calendarFormatという変数に3つのカレンダーフォーマットを用意します。

// カレンダーフォーマット配列
final _calendarFormat = [CalendarFormat.month, CalendarFormat.twoWeeks, CalendarFormat.week]; 

そもそもカレンダーフォーマットとは?気になる方はこちらをご参考ください。

【Flutter】table_calendarでカレンダー作成

タップした際に変更できるようにする

アプリ右上にある2 weeksとあるボタンをタップしたら変更できるようにonFormatChanged:を設定します。

もしuseStateの値(formatIndex.value)がタップされた際のフォーマット(format引数)のインデックスでなければというif分を作成しています。

if分に入ってきたらタップされた値useStateの値(formartIndex)に代入しています。

        onFormatChanged: (format) {  // 「月」「週」変更
                  if (formatIndex.value != format.index) { 
                    formatIndex.value = format.index; 
                  }
                },

カレンダー表示

実際に表示されるためには、calendarFormat:に設定する必要があるため設定します。


宣言したカレンダーフォーマットの配列(_calendarFormat)を表示します。


何番目を表示するかの[]の部分にuseStateの値(formatIndex)を設置することでタップされ変更されるたびに見た目が変わる(選択されたフォーマットを表次)することができます。

// 表示するカレンダーフォーマット
calendarFormat: _calendarFormat[formatIndex.value], 

全体の実装内容

//カレンダーページ
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:table_calendar/table_calendar.dart';

class CalendarPage extends HookWidget {
   CalendarPage({Key? key}) : super(key: key);

  DateTime _focusedDay = DateTime.now(); // 現在日
  DateTime? _selectedDay; // 選択している日付
  List<String> _selectedEvents = [];
  // カレンダーフォーマット配列
  final _calendarFormat = [CalendarFormat.month, CalendarFormat.twoWeeks, CalendarFormat.week]; // カレンダーフォーマット配列

  //Map形式で保持 keyが日付 値が文字列
  final sampleMap = {
    DateTime.utc(2023, 3,20): ['firstEvent', 'secondEvent'],
    DateTime.utc(2023, 3,5): ['thirdEvent', 'fourthEvent'],
  };

  final sampleEvents = {
    DateTime.utc(2023, 3,20): ['firstEvent', 'secondEvent'],
    DateTime.utc(2023, 3,5): ['thirdEvent', 'fourthEvent']
  };
  @override
  Widget build(BuildContext context) {
    final formatIndex = useState(0);
    return Scaffold(
      // カレンダーUI実装
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(20.0),
            child: TableCalendar(
                firstDay: DateTime.utc(2023, 1, 1),
                lastDay: DateTime.utc(2024, 12, 31),
                focusedDay: _focusedDay,
                eventLoader: (date) { // イベントドット処理
                  return sampleMap2024/12/03 ?? [];
                },
          // 表示するカレンダーフォーマット
                calendarFormat: _calendarFormat[formatIndex.value], 
                onFormatChanged: (format) {  // 「月」「週」変更
                  if (formatIndex.value != format.index) { 
                    formatIndex.value = format.index; 
                },
                // 選択日のアニメーション
                selectedDayPredicate: (day) {
                  return isSameDay(_selectedDay, day);
                },
                // 日付が選択されたときの処理
                onDaySelected: (selectedDay, focusedDay) {
                }
            ),
          ),
          // タップした時表示するリスト
          Expanded(
            child: ListView.builder(
              itemCount: _selectedEvents.length,
              itemBuilder: (context, index) {
                final event = _selectedEvents[index];
                return Card(
                  child: ListTile(
                    title: Text(event),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

最後に

簡単ではありますが、フォーマット部分をFlutter Hooksで実装しました。
他の部分もHooksで設定できそうなので随時更新できたらと思います。

ではまた。

コメント

タイトルとURLをコピーしました