flutter

table calendar flutter provider

햎피 2022. 6. 7. 22:08
반응형

flutter에서 table calendar를 provider를 이용하는 방법에 대해서 알아보겠다.

stateful widget에서 사용하는 예제는 table calendar github 예제에 이미 나와있다.

https://github.com/aleksanderwozniak/table_calendar/tree/master/example

 

GitHub - aleksanderwozniak/table_calendar: Highly customizable, feature-packed calendar widget for Flutter

Highly customizable, feature-packed calendar widget for Flutter - GitHub - aleksanderwozniak/table_calendar: Highly customizable, feature-packed calendar widget for Flutter

github.com

 

이 포스팅에서는 provider 패턴에서 table calendar 사용하는 방법을 알아볼 것이다.

 

화면부분은 세부분으로 나뉜다. 첫번째는 monthscreen 전체 위젯을 배열해줬다. 이 부분은 모두 알것이므로 설명을 패스하겠다.

class MonthScreen extends StatelessWidget {
  const MonthScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [SizedBox(height: 8.0), Tablecalendar(), Eventlist()],
    ));
  }
}

 

두번째 부분은 table calendar 부분이다. 좀 자세히 설명하겠다.

class Tablecalendar extends StatelessWidget {
  late calendarModel calendarmodel;
  Tablecalendar({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    calendarmodel = Provider.of<calendarModel>(context);

Model 부분에서 데이터를 가져와야하므로 provider 선언을 해준다.  그리고 tablecalendar 위젯을 리턴해준다.

return Column(
      children: [
        TableCalendar<EventModel>(
            locale: Localizations.localeOf(context).languageCode,

 

여기서 한국어로 사용하려면 

pubspec.yaml 파일의 dependencies부분에

flutter_localizations:
    sdk: flutter

를 작성하고 컨트롤 s로 저장해서 패키지를 다운받고,

main 의 materialapp 부분에 아래와 같이 localizationsDelegates~~, supportedLocales~~를 추가해줘야한다.

child: MaterialApp(
        localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('en', ''), // English, no country code
        const Locale('ko', ''),
      ],
        title: 'App',
        ...

하여튼 그 다음에, table calendar 내부의 변수들에 대해서 데이터를 가져와야하는 것들은 Model 부분에서 가져와준다.

firstDay: kToday,
lastDay: kLastDay,
focusedDay: calendarmodel.focusedDay,
selectedDayPredicate: (day) =>
    isSameDay(calendarmodel.selectedDay, day),
onDaySelected: calendarmodel.onDaySelected,
eventLoader: calendarmodel.getEventsForDay,

 

 
화면 부분의 전체 소스코드이다.
class MonthScreen extends StatelessWidget {
  const MonthScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [SizedBox(height: 8.0), Tablecalendar(), Eventlist()],
    ));
  }
}
//table calendar 시작
class Tablecalendar extends StatelessWidget {
  //provider 정의
  late calendarModel calendarmodel;
  Tablecalendar({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //provider 정의
    calendarmodel = Provider.of<calendarModel>(context);
    return Column(
      children: [
        TableCalendar<EventModel>(
            locale: Localizations.localeOf(context).languageCode,
            headerStyle: HeaderStyle(
                formatButtonVisible: false,
                titleCentered: true,
                leftChevronVisible: false,
                rightChevronVisible: false),
            firstDay: kToday,
            lastDay: kLastDay,
            //focusedDay, selectedDay는 provider에서 값을 가져다쓰고 업데이트함.
            focusedDay: calendarmodel.focusedDay,
            selectedDayPredicate: (day) =>
                isSameDay(calendarmodel.selectedDay, day),
            //선택 날짜가 바뀔경우
            onDaySelected: calendarmodel.onDaySelected,
            calendarFormat: CalendarFormat.month,
       		//event loader
            eventLoader: calendarmodel.getEventsForDay,
            startingDayOfWeek: StartingDayOfWeek.monday,
            calendarStyle: CalendarStyle(
                isTodayHighlighted: true,
                outsideDaysVisible: false,
                markerDecoration: BoxDecoration()),
            calendarBuilders:
                CalendarBuilders(markerBuilder: (context, date, dynamic event) {
              if (event.isNotEmpty) {
                return Container(
                  width: 35,
                  decoration: BoxDecoration(
                      color: Colors.blue.withOpacity(0.2),
                      shape: BoxShape.circle),
                );
              }
            })),
        SizedBox(height: 8.0),
      ],
    );
  }
}

class Eventlist extends StatelessWidget {
  late calendarModel calendarmodel;

  Eventlist({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    calendarmodel = Provider.of<calendarModel>(context);

    return Expanded(
      child: Column(
        children: [
          ListView.builder(
              scrollDirection: Axis.vertical,
              shrinkWrap: true,
              itemCount: calendarmodel.selectedEvents.length,
              itemBuilder: (context, index) {
                return Container(
                  margin: const EdgeInsets.symmetric(
                    horizontal: 12.0,
                    vertical: 4.0,
                  ),
                  decoration: BoxDecoration(
                    border: Border.all(),
                    borderRadius: BorderRadius.circular(12.0),
                  ),
                  child: ListTile(
                    onTap: () => print(calendarmodel.selectedEvents[index]),
                    title: Text(calendarmodel.selectedEvents[index].toString()),
                  ),
                );
              })
        ],
      ),
    );
  }
}

 

모델부분의 전체 소스 코드이다.

class EventModel extends ChangeNotifier {
  String title;

  EventModel(this.title);

  @override
  String toString() => title;
}

final kToday = DateTime.now().toLocal();
final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day);

int getHashCode(DateTime key) {
  return key.day * 1000000 + key.month * 10000 + key.year;
}

class calendarModel extends ChangeNotifier {
  DateTime _focusedDay = DateTime.now().toUtc();
  DateTime? _selectedDay;
  List<EventModel>? _selectedEvents;
  final _events = LinkedHashMap<DateTime, List<EventModel>> (
    equals:isSameDay,
    hashCode: getHashCode)..addAll({
    DateTime.utc(2022, 06, 07): [EventModel('hi')],
    DateTime.utc(2022, 06, 08): [EventModel('hi')]
  });

  get focusedDay => _focusedDay;
  get selectedDay => _selectedDay;
  get selectedEvents => _selectedEvents;
  get onDaySelected => _onDaySelected;
  get events => _events;
  get getEventsForDay => _getEventsForDay;

  calendarModel() {
    _selectedDay = _focusedDay.toUtc();
    _selectedEvents = _events[_selectedDay?.toUtc()]??[];
    notifyListeners();
  }

  _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
    if (!isSameDay(_selectedDay, selectedDay)) {
      _selectedDay = selectedDay;
      _focusedDay = focusedDay;
      notifyListeners();
    }
    _selectedEvents = _events[_selectedDay]??[];
    notifyListeners();
  }

  List<EventModel> _getEventsForDay(DateTime day) {

    return _events[day] ?? [];
  }
}

설명하기가 너무 어렵다,,,ㅠ

혹시 이해가 안가거나 질문이 있으면 댓글로 남겨주셔요,,,

반응형