Flutter Package 탐방: table_calendar

손세은·2023년 12월 1일

사용 목적:

  • 어플에 예쁜 캘린더를 달아서 스케줄러, 투두리스트 등을 만들어보자자자잇!

패키지 링크:

https://pub.dev/packages/table_calendar

사용 예시:

기본

  • required DateTime
TableCalendar(
  focusedDay: DateTime.now(),    //현재 포커스 되어 있는 날짜
  firstDay: DateTime.utc(2010, 10, 16), //스크롤 했을 때 가장 첫번째 날짜
  lastDay: DateTime.utc(2030, 3, 14),   //스크롤 했을 때 가장 마지막 날짜
);
  • 상단 헤더 꾸미기
TableCalendar(
      firstDay: DateTime.utc(2010, 10, 16),
      lastDay: DateTime.utc(2030, 3, 14),
      focusedDay: DateTime.now(),
      headerStyle: HeaderStyle(
        formatButtonVisible: false, // 상단 2weeks 버튼 제거
        titleCentered: true, // 상단 title 가운데 정렬
        titleTextStyle: TextStyle(fontWeight: FontWeight.w700), //title style 변경
      ),
  • 날짜가 선택이 됐을 때 실행 되는 함수
DateTime _selectedDay = DateTime.now();

TableCalendar(
      firstDay: DateTime.utc(2010, 10, 16),
      lastDay: DateTime.utc(2030, 3, 14),
      focusedDay: DateTime.now(),
      onDaySelected: (DateTime selectedDay, DateTime focusedDay) {  //selectedDay, focusedDay를 인자로 받는다
        setState((){
           _selectedDay = selectedDay;
         //선언한 _selectedDay 변수에
         //내가 선택한 일자, selectedDay 넣어주기
         //setState로 상태변화
        });
      },
    );
  • 포커스된 오늘 날짜 따로, 선택된 날짜 따로 표기(선택된 날짜 표기)
DateTime _selectedDay = DateTime.now();

TableCalendar(
      firstDay: DateTime.utc(2010, 10, 16),
      lastDay: DateTime.utc(2030, 3, 14),
      focusedDay: DateTime.now(),
      onDaySelected: (DateTime selectedDay, DateTime focusedDay) {
        setState(() {
          _selectedDay = selectedDay;
        });
      },
      selectedDayPredicate: (DateTime date) {
        if (_selectedDay == null) {
          //아무것도 선택되지 않았을 때
          return false;
        }
        return date.year == _selectedDay!.year &&
            date.month == _selectedDay!.month &&
            date.day == _selectedDay!.day;
        //date == _selectedDay; : (시, 분, 초까지 정확히 일치시킴)
      },
    );

캘린더 바디 스타일링


    final defaultBoxDecoration = BoxDecoration(
      borderRadius: BorderRadius.circular(10),
      color: Colors.grey[200],
    );

    final defaultTextStyle = TextStyle(
      color: Colors.grey[700],
      fontWeight: FontWeight.bold,
    );


TableCalendar(
      firstDay: DateTime.utc(2010, 10, 16),
      lastDay: DateTime.utc(2030, 3, 14),
      focusedDay: DateTime.now(),
      calendarStyle: CalendarStyle(
          selectedTextStyle: defaultTextStyle.copyWith(color: Colors.white),
          weekendTextStyle: defaultTextStyle, // 선택할 수 있는 날짜(주말)의 text style
          defaultTextStyle:
              defaultTextStyle, // 선택할 수 있는 날짜(평일)의 default text style
          isTodayHighlighted: false, // 포커스된 오늘 날짜 하이라이트 제거
          defaultDecoration:
              defaultBoxDecoration, // 선택할 수 있는 날짜(평일)의 default 스타일
          weekendDecoration:
              defaultBoxDecoration, // 선택할 수 있는 날짜(주말)의 default 스타일
          selectedDecoration: defaultBoxDecoration.copyWith(
              color: AppColors.primaryColor) // 선택된 날짜의 스타일

          ),
    );

버그수정

  • 버그 발생 이유
  • 버그 해결:
   calendarStyle: CalendarStyle(
         ** outsideDecoration:
              BoxDecoration(shape: BoxShape.rectangle), // 선택할 수 없는 날짜의 스타일**
          selectedTextStyle: defaultTextStyle.copyWith(color: Colors.white),
          weekendTextStyle: defaultTextStyle, // 선택할 수 있는 날짜(주말)의 text style
          defaultTextStyle:
              defaultTextStyle, // 선택할 수 있는 날짜(평일)의 default text style
          isTodayHighlighted: false, // 포커스된 오늘 날짜 하이라이트 제거
          defaultDecoration:
              defaultBoxDecoration, // 선택할 수 있는 날짜(평일)의 default 스타일
          weekendDecoration:
              defaultBoxDecoration, // 선택할 수 있는 날짜(주말)의 default 스타일
          selectedDecoration: defaultBoxDecoration.copyWith(
              color: AppColors.primaryColor) // 선택된 날짜의 스타일

          ),
  1. 클릭할 수 없는 날짜를 누르면은 그 날짜의 달로 이동하지 않음
  • 버그 발생 이유:
  • 버그 해결:
  DateTime _focusedDay = DateTime.now();
  //_focusedDay 선언
  
  TableCalendar(
      firstDay: DateTime.utc(2010, 10, 16),
      lastDay: DateTime.utc(2030, 3, 14),
      focusedDay: _focusedDay,
      headerStyle: HeaderStyle(
        formatButtonVisible: false, // 상단 2weeks 버튼 제거
        titleCentered: true, // 상단 title 가운데 정렬
        titleTextStyle: TextStyle(fontWeight: FontWeight.w700), //title style 변경
      ),
      onDaySelected: (DateTime selectedDay, DateTime focusedDay) {
        setState(() {
          _selectedDay = selectedDay;
          _focusedDay = selectedDay;
        });
      },
    ),

세은이의 캘린더 위젯

import 'package:calendar_scheduler/view/const/colors.dart';
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';

class Calendar extends StatefulWidget {
  const Calendar({super.key});

  @override
  State<Calendar> createState() => _CalendarState();
}

class _CalendarState extends State<Calendar> {
  DateTime _selectedDay = DateTime.now();
  DateTime _focusedDay = DateTime.now();

  @override
  Widget build(BuildContext context) {
    final defaultBoxDecoration = BoxDecoration(
      borderRadius: BorderRadius.circular(10),
      color: Colors.grey[200],
    );

    final defaultTextStyle = TextStyle(
      color: Colors.grey[700],
      fontWeight: FontWeight.bold,
    );

    return TableCalendar(
      firstDay: DateTime.utc(2010, 10, 16),
      lastDay: DateTime.utc(2030, 3, 14),
      focusedDay: _focusedDay,
      headerStyle: HeaderStyle(
        formatButtonVisible: false, // 상단 2weeks 버튼 제거
        titleCentered: true, // 상단 title 가운데 정렬
        titleTextStyle: TextStyle(fontWeight: FontWeight.w700), //title style 변경
      ),
      onDaySelected: (DateTime selectedDay, DateTime focusedDay) {
        setState(() {
          _selectedDay = selectedDay;
          _focusedDay = selectedDay;
        });
      },
      calendarStyle: CalendarStyle(
          outsideDecoration:
              BoxDecoration(shape: BoxShape.rectangle), // 선택할 수 없는 날짜의 스타일
          selectedTextStyle: defaultTextStyle.copyWith(color: Colors.white),
          weekendTextStyle: defaultTextStyle, // 선택할 수 있는 날짜(주말)의 text style
          defaultTextStyle:
              defaultTextStyle, // 선택할 수 있는 날짜(평일)의 default text style
          isTodayHighlighted: false, // 포커스된 오늘 날짜 하이라이트 제거
          defaultDecoration:
              defaultBoxDecoration, // 선택할 수 있는 날짜(평일)의 default 스타일
          weekendDecoration:
              defaultBoxDecoration, // 선택할 수 있는 날짜(주말)의 default 스타일
          selectedDecoration: defaultBoxDecoration.copyWith(
              color: AppColors.primaryColor) // 선택된 날짜의 스타일

          ),
      selectedDayPredicate: (DateTime date) {
        if (_selectedDay == null) {
          //아무것도 선택되지 않았을 때
          return false;
        }
        return date.year == _selectedDay!.year &&
            date.month == _selectedDay!.month &&
            date.day == _selectedDay!.day;
        //date == _selectedDay; : (시, 분, 초까지 정확히 일치해야함)
      },
    );
  }
}
profile
힙스터 개발자가 될래요

0개의 댓글