Flutter/Package

[Flutter] TableCalendar ⑤ - 유용한 기능들

찌김이 2022. 7. 20. 16:45
728x90
반응형

TableCalendar ① - 간단한 달력 구현  https://dalgoodori.tistory.com/14

TableCalendar ② - 달력 언어 설정 (locale)  https://dalgoodori.tistory.com/15

TableCalendar ③ - 달력 꾸미기 (HeaderStyle)  https://dalgoodori.tistory.com/16

TableCalendar - 달력 꾸미기 (CalendarStyle)  https://dalgoodori.tistory.com/17

TableCalendar ⑤ - 유용한 기능들

 

TableCalendar 는 여러 기능들이 있지만 사용자가 별도로 구현해놓지 않으면 깡통 달력과 다를바 없습니다.

이번에는 가장 많이 쓰이는 기능 3가지를 알아보려 합니다.

 

1. 날짜 선택 처리

  • TableCalendar 는 날짜를 클릭해도 아무 이벤트가 일어나지 않으며, 날짜 선택에 대한 처리를 별도로 해줘야 합니다.
  • 날짜 선택 처리 인자는 onDaySelected, selectedDayPredicate 로 할 수 있습니다.

 

  • onDaySelected 에서는 날짜 선택 시 DateTime 타입의 selectedDay , focusedDay 를 받을 수 있습니다.
typedef OnDaySelected = void Function(
    DateTime selectedDay, DateTime focusedDay);

 

  • selectedDayPredicate 는 날짜 선택 시 Datetime 타입의 day 를 받을 수 있고 bool 타입을 반환해야 합니다.
final bool Function(DateTime day)? selectedDayPredicate;

 

 

  • 선택한 날짜의 상태를 관리하기 위해 StatelessWidgetStatefullWidget 으로 변경
  • DateTime 타입의 변수 selectedDay , focusedDay 를 선언합니다.
DateTime selectedDay = DateTime(
  DateTime.now().year,
  DateTime.now().month,
  DateTime.now().day,
);

DateTime focusedDay = DateTime.now();

 

  • onDaySelected, selectedDayPredicate 를 넣어주면 날짜 선택이 잘 동작하는 것을 확인할 수 있습니다.
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';

class TableCalendarScreen extends StatefulWidget {
  const TableCalendarScreen({Key? key}) : super(key: key);

  @override
  State<TableCalendarScreen> createState() => _TableCalendarScreenState();
}

class _TableCalendarScreenState extends State<TableCalendarScreen> {

  DateTime selectedDay = DateTime(
    DateTime.now().year,
    DateTime.now().month,
    DateTime.now().day,
  );

  DateTime focusedDay = DateTime.now();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: TableCalendar(
        locale: 'ko_KR',
        firstDay: DateTime.utc(2021, 10, 16),
        lastDay: DateTime.utc(2030, 3, 14),
        focusedDay: focusedDay,
        onDaySelected: (DateTime selectedDay, DateTime focusedDay) {
          // 선택된 날짜의 상태를 갱신합니다.	
          setState((){
            this.selectedDay = selectedDay;
            this.focusedDay = focusedDay;
          });
        },
        selectedDayPredicate: (DateTime day) {
          // selectedDay 와 동일한 날짜의 모양을 바꿔줍니다.	
          return isSameDay(selectedDay, day);
        },
      ),
    );
  }
}

 

 

2. marker 표시

  • 해당 날짜에 event 가 있음을 나타내는 marker 설정은 eventLoader 로 구현할 수 있습니다.

 

  • eventLoader 는 Datetime 타입의 day 를 받아 제네릭 리스트를 반환합니다.
final List<T> Function(DateTime day)? eventLoader;

 

  • eventLoader 에 쓰일 임의의 class 를 만듭니다. 
class Event {
  String title;

  Event(this.title);
}

 

  • eventLoader 에 사용될 변수를 선언하고, 해당 날짜에 event 목록을 반환하는 _getEventsForDay 를 만듭니다.
Map<DateTime, List<Event>> events = {
  DateTime.utc(2022,7,13) : [ Event('title'), Event('title2') ],
  DateTime.utc(2022,7,14) : [ Event('title3') ],
};

List<Event> _getEventsForDay(DateTime day) {
  return events[day] ?? [];
}

 

  • _getEventsForDay 를 eventLoader 에 넣어주면 구현이 완료됩니다.
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';

class TableCalendarScreen extends StatefulWidget {
  const TableCalendarScreen({Key? key}) : super(key: key);

  @override
  State<TableCalendarScreen> createState() => _TableCalendarScreenState();
}

class _TableCalendarScreenState extends State<TableCalendarScreen> {

  Map<DateTime, List<Event>> events = {
    DateTime.utc(2022,7,13) : [ Event('title'), Event('title2') ],
    DateTime.utc(2022,7,14) : [ Event('title3') ],
  };

  List<Event> _getEventsForDay(DateTime day) {
    return events[day] ?? [];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: TableCalendar(
        locale: 'ko_KR',
        firstDay: DateTime.utc(2021, 10, 16),
        lastDay: DateTime.utc(2030, 3, 14),
        focusedDay: DateTime.now(),
        calendarStyle: CalendarStyle(
          markerSize: 10.0,
          markerDecoration: BoxDecoration(
            color: Colors.red,
            shape: BoxShape.circle
          ),
        ),
        eventLoader: _getEventsForDay,
      ),
    );
  }
}

class Event {
  String title;

  Event(this.title);
}

 

3. format 변경

  • 달력을 달, 2주, 1주 씩 보이게 하는 기능이며 onFormatChanged 로 구현 가능합니다.
  • formatButton 을 클릭하거나 달력을 위, 아래 제스처로 동작합니다.
  • 하지만 onFormatChanged 이 설정되어 있지 않다면 에러가 뜹니다.

 

  • onFormatChanged 는 format 변경 시 CalendarFormat 타입의 format 을 받을 수 있습니다. 
final void Function(CalendarFormat format)? onFormatChanged;

 

  • format 상태를 저장할 변수를 선언합니다.
CalendarFormat format = CalendarFormat.month;

 

  • onFormatChanged 에서 상태를 갱신하는 것을 구현하면 format이 바뀌는 것을 볼 수 있습니다.
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';

class TableCalendarScreen extends StatefulWidget {
  const TableCalendarScreen({Key? key}) : super(key: key);

  @override
  State<TableCalendarScreen> createState() => _TableCalendarScreenState();
}

class _TableCalendarScreenState extends State<TableCalendarScreen> {
	
  // format 상태 저장할 변수
  CalendarFormat format = CalendarFormat.month;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: TableCalendar(
        locale: 'ko_KR',
        firstDay: DateTime.utc(2021, 10, 16),
        lastDay: DateTime.utc(2030, 3, 14),
        focusedDay: DateTime.now(),
        
        // 추가
        calendarFormat: format,
        onFormatChanged: (CalendarFormat format) {
          setState(() {
            this.format = format;
          });
        },
      ),
    );
  }
}
728x90
반응형