이번 포스트에서는 진행하는 프로젝트 내에서 사용한 컴포넌트를 기록해 보겠습니다.
✔️ 들어가며,
프로젝트 내에서 사용할 캘린더 기능을 구현하기 위해서, 간단히 연습으로 캘린더 기능을 혼자 구현해 보았습니다.
TableCalendar 라는 좋은 패키지가 있지만, 스스로 구현해 보고 싶은 마음에 없이 진행하였습니다.
기능에는 디데이 기능, 일정 추가 및 삭제, 바텀 시트로 일정 확인하기 세 가지가 있습니다.
차근 차근 포스트 해 보며, 공부했던 내용을 기록해 보겠습니다!
이번에는 GetX 와 MVC 패턴을 이용하여 코드를 구성하였는데, 두 개 다 접해 보지 못 한 부분이라 미숙할 수 있지만,
기능과 UI 위주로 작성한 것이니, 위 내용은 나중에 다시 포스팅 해 보겠습니다.




위와 같은 사진처럼 나타낼 예정입니다!
✔️ 캘린더 UI 코드 작성해 보기!
final DateTime now = DateTime.now(); // 현재 날짜 기준
final List<String> daysOfWeek = ['일', '월', '화', '수', '목', '금', '토'];
/// 캘린더 전체 UI
Widget _schedule() {
DateTime firstDayOfMonth = DateTime(now.year, now.month, 1);
int daysInMonth = DateTime(now.year, now.month + 1, 0).day;
int firstWeekday = firstDayOfMonth.weekday % 7;
int totalCells = firstWeekday + daysInMonth;
return Column(
children: [
_buildDaysOfWeekHeader(),
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 7,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
),
itemCount: totalCells,
itemBuilder: (context, index) {
if (index < firstWeekday) {
return Container(); // 빈 칸
} else {
int day = index - firstWeekday + 1;
return _buildDayCard(context, day);
}
},
),
),
],
);
}
/// 요일 헤더 (일~토)
Widget _buildDaysOfWeekHeader() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: daysOfWeek.map((day) {
return Text(
day,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
);
}).toList(),
);
}
/// 각 날짜 UI
Widget _buildDayCard(BuildContext context, int day) {
return GestureDetector(
onTap: () => _showBottomSheet(context, day),
child: Card(
elevation: 2,
color: day == now.day ? Colors.pink : Colors.white,
child: Center(
child: Text(
'$day',
style: TextStyle(
fontSize: 16,
color: day == now.day ? Colors.white : Colors.black,
),
),
),
),
);
}
✔️ 코드 설명
저는 먼저, 그리드 뷰를 사용하여서 7 일이니 7 열 구조로 달력을 구성해 보았습니다.
그리고 DateTime 클래스를 이용하여, 계산에 용이하도록 하였습니다. 여기서 기억하면 좋을 것 같은 부분은
DateTime(now.year, now.month + 1, 0).day
마지막 달이 30 일과 31 일 상관 없이 0 으로 설정하여,
다음 달의 0 일 = 이번 달의 마지막 날임을 이용해 간단하게 코드로 나타내었습니다.
int firstWeekday = DateTime(now.year, now.month, 1).weekday % 7;
또한, 달력의 빈 칸까지 함께 고려하였습니다.
itemCount: totalCells,
itemBuilder: (context, index) {
if (index < firstWeekday) {
return Container();
} else {
int day = index - firstWeekday + 1;
return _buildDayCard(context, day);
}
},
index 의 앞이 빈 날이라면 빈 칸을 출력하고, 빈 날이 아니라면 실제 날짜를 출력합니다.
✨ 아쉬운 점
이번 코드를 빠르게 작성하려다 보니, 디테일한 부분까지 생각하지 못 했습니다!
Card 대신 Container 를 사용하면 조금 더 좋은 코드가 되었을 것 같습니다. 또한 월 기능을 추가하여 현재 날짜의 달만 보이지 않고 다음 달, 이전 달도 확인할 수 있도록 코드를 구성하면 좋겠다는 생각이 듭니다.
기능을 추가한 코드도 업로드 할 예정이니, 올리게 된다면 첨부하도록 하겠습니다!
다음 플러터 포스트는 일정을 추가하는 기능을 넣은 코드로 포스트 해 보겠습니당. ㅎㅎ
'Flutter' 카테고리의 다른 글
[Flutter] 캘린더에 일정 추가 기능 구현하기 (0) | 2025.03.29 |
---|---|
[Flutter] GetX MVC 패턴과 Provider MVVM 패턴 (0) | 2025.03.06 |
[Flutter] flutter 의 렌더링 - Skia 엔진이란 무엇인가? (0) | 2025.01.03 |
[Flutter] 상태 관리와 랜더링 이해하기 (0) | 2024.12.21 |
[Flutter] Random - 랜덤으로 숫자 받기 (0) | 2024.11.28 |