티스토리 뷰

반응형

Flutter를 위한 높은 커스터마이징 가능성과 기능이 풍부한 캘린더 위젯이다.

 

특징

  • 광범위하면서도 사용하기 쉬운 API
  • 커스터마이징 가능한 스타일의 기본 UI
  • 무제한 UI 디자인을 위한 커스텀 선택 빌더
  • 로케일 지원
  • 범위 선택 지원
  • 다중 선택 지원
  • 동적 이벤트 및 휴일
  • 수직 자동 크기 조정 - 내용에 맞게 조정하거나 뷰포트를 채우기
  • 여러 캘린더 형식 (월, 2주, 주)
  • 수평 스와이프 경계 (첫날, 마지막 날)

 

설치

pubspec.yaml에 다음 줄을 추가하세요:

dependencies:
  table_calendar: ^3.1.2

 

 

기본 설정

TableCalendar는 firstDay, lastDayfocusedDay를 제공해야 합니다:

  • firstDay: 캘린더에서 사용할 수 있는 첫 번째 날. 이 날 이전의 날에는 접근할 수 없습니다.
  • lastDay: 캘린더에서 사용할 수 있는 마지막 날. 이 날 이후의 날에는 접근할 수 없습니다.
  • focusedDay: 현재 선택된 날. 이 속성을 사용하여 현재 표시할 월을 결정합니다.
TableCalendar(
  firstDay: DateTime.utc(2010, 10, 16),
  lastDay: DateTime.utc(2030, 3, 14),
  focusedDay: DateTime.now(),
);

 

인터랙티브 추가하기

기본 캘린더 위젯은 수평으로 스와이프하여 현재 표시된 월을 변경하는 것 외에는 그다지 인터랙티브하지 않습니다. 특정 콜백을 지정하면 쉽게 인터랙티브하게 만들 수 있습니다.

사용자의 탭에 반응하여 탭한 날을 선택된 것으로 표시하려면 다음 코드를 추가하세요:

selectedDayPredicate: (day) {
  return isSameDay(_selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
  setState(() {
    _selectedDay = selectedDay;
    _focusedDay = focusedDay; // `_focusedDay`도 여기에서 업데이트합니다.
  });
},

 

동적으로 표시되는 캘린더 형식을 업데이트하려면 다음 코드를 추가하세요:

calendarFormat: _calendarFormat,
onFormatChanged: (format) {
  setState(() {
    _calendarFormat = format;
  });
},

 

이 두 가지 변경 사항을 통해 캘린더가 인터랙티브하고 사용자 입력에 반응하도록 할 수 있습니다.

 

focusedDay 업데이트

focusedDay를 정적 값으로 설정하면 TableCalendar 위젯이 재구성될 때마다 그 특정 focusedDay를 사용하게 됩니다. 빠르게 테스트하려면 focusedDayDateTime.now()로 설정하고 다음 월로 스와이프한 후 핫 리로드를 트리거하세요 - 캘린더가 "초기 상태"로 "리셋"됩니다. 이를 방지하려면 콜백이 focusedDay를 노출할 때마다 이를 저장하고 업데이트해야 합니다.

다음 콜백을 추가하여 기본 설정을 완료하세요:

onPageChanged: (focusedDay) {
  _focusedDay = focusedDay;
},

onPageChanged() 콜백 안에서 setState()를 호출할 필요는 없습니다. 저장된 값을 업데이트하기만 하면 나중에 위젯이 재구성될 때 적절한 focusedDay를 사용할 수 있습니다.

완전한 예제는 여기에서 확인할 수 있습니다. 다른 예제는 여기에서 확인할 수 있습니다.

 

이벤트

완전한 예제는 여기에서 확인할 수 있습니다.

TableCalendar 위젯에 커스텀 이벤트를 제공할 수 있습니다. 이를 위해 eventLoader 속성을 사용하세요 - DateTime 객체가 제공되며, 이 객체에 이벤트 목록을 할당해야 합니다.

eventLoader: (day) {
  return _getEventsForDay(day);
},

_getEventsForDay()는 어떤 구현도 가능하며, 예를 들어 Map<DateTime, List<T>>를 사용할 수 있습니다:

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

기억할 점은 DateTime 객체가 날짜와 시간 부분 모두로 구성되어 있다는 것입니다. 많은 경우 이 시간 부분은 캘린더 관련 측면에서 불필요합니다.

맵을 사용할 경우 LinkedHashMap을 사용하는 것이 좋습니다 - 이렇게 하면 두 DateTime 객체의 날짜 부분만 비교하여 동등성 비교를 재정의할 수 있습니다:

final events = LinkedHashMap(
  equals: isSameDay,
  hashCode: getHashCode,
)..addAll(eventSource);

 

주기적인 이벤트

eventLoader를 사용하면 패턴에 따라 반복되는 이벤트를 쉽게 추가할 수 있습니다. 예를 들어, 매주 월요일에 이벤트를 추가하려면 다음 코드를 사용할 수 있습니다:

eventLoader: (day) {
  if (day.weekday == DateTime.monday) {
    return [Event('Cyclic event')];
  }

  return [];
},

 

탭으로 선택된 이벤트

하루를 탭하여 선택된 이벤트의 하위 목록을 가지는 것이 자주 필요합니다. 이를 달성하려면 onDaySelected 콜백 안에 eventLoader에 제공한 동일한 방법을 사용할 수 있습니다:

void _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
  if (!isSameDay(_selectedDay, selectedDay)) {
    setState(() {
      _focusedDay = focusedDay;
      _selectedDay = selectedDay;
      _selectedEvents = _getEventsForDay(selectedDay);
    });
  }
}

 

완전한 예제는 여기에서 확인할 수 있습니다.

 

CalendarBuilders로 사용자 정의 UI

자신만의 위젯으로 UI를 커스터마이즈하려면 CalendarBuilders를 사용하세요. 각 빌더를 사용하여 UI를 선택적으로 오버라이드할 수 있으며, 최소한의 노력으로 매우 구체적인 디자인을 구현할 수 있습니다.

어떤 빌더에서 null을 반환하면 기본 스타일이 사용됩니다. 예를 들어, 다음 코드 조각은 일요일의 주중 레이블(Sun)만 오버라이드하며, 다른 주중 레이블은 변경하지 않습니다:

calendarBuilders: CalendarBuilders(
  dowBuilder: (context, day) {
    if (day.weekday == DateTime.sunday) {
      final text = DateFormat.E().format(day);

      return Center(
        child: Text(
          text,
          style: TextStyle(color: Colors.red),
        ),
      );
    }
  },
),

 

로케일

캘린더를 원하는 언어로 표시하려면 locale 속성을 사용하세요. 이를 지정하지 않으면 기본 로케일이 사용됩니다.

 

초기화

로케일을 사용하기 전에 날짜 형식을 초기화해야 할 수도 있습니다.

간단한 방법은 다음과 같습니다:

  1. intl 패키지를 pubspec.yaml 파일에 추가합니다.
  2. main()을 다음과 같이 수정합니다:
import 'package:intl/date_symbol_data_local.dart';

void main() {
  initializeDateFormatting().then((_) => runApp(MyApp()));
}

이 두 단계를 수행한 후, 앱은 다양한 언어로 TableCalendar를 사용할 준비가 됩니다.

 

언어 지정

언어를 지정하려면 locale 속성에 문자열 코드를 전달하세요.

예를 들어, TableCalendar를 폴란드어로 설정하려면:

TableCalendar(
  locale: 'pl_PL',
),

 

참고: FormatButton의 텍스트 언어를 변경하려면 직접 수행해야 합니다. availableCalendarFormats 속성을 사용하고, 번역된 문자열을 전달하세요. 원하는 i18n 방법을 사용하세요.

또한, formatButtonVisible을 false로 설정하여 버튼을 완전히 숨길 수도 있습니다.

반응형
댓글
공지사항