반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- JPA예제
- 자바공부
- 플러터 개발
- querydsl
- 카프카
- 스프링
- JPA 공부
- 스프링 공부
- K8S
- 기술면접공부
- nestjs스터디
- DDD
- 알고리즘공부
- 프로그래머스
- JPA
- JPA스터디
- 코테공부
- nestjs공부
- 플러터 공부
- 스프링부트공부
- Axon framework
- 스프링부트
- Flutter
- nestjs
- 코테준비
- 자료구조공부
- JPA공부
- Kafka
- 스프링공부
- 기술공부
Archives
- Today
- Total
DevBoi
[Flutter] TableCalendar EventHandler 본문
반응형
플러터에서 달력에 대한 오픈소스를 사용하면서 이벤트 관련 내용을 개발했다.
개발 기능은 아래와 같다.
1. 일정 내용을 로드
2. 달력 컴포넌트에 일정을 표시
3. 일정을 클릭시 해당 일정에 대한 상세 내용 확인
4. 해당 상세 내용 클릭시, 팝업으로 그룹에 내용 표기
무튼 소스 내용은 아래와 같다.
1. 화면소스
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:flutter_naver_map/flutter_naver_map.dart';
import 'package:get/get.dart';
import 'package:goodshot/global-provider.dart';
import 'package:goodshot/util/const.dart';
import 'package:goodshot/view/group/http/group-api.dart';
import 'package:goodshot/view/group/http/group-join-api.dart';
import 'package:goodshot/view/group/popup/group-detail-popup.dart';
import 'package:goodshot/view/group/popup/group-schedule-detail-popup.dart';
import 'package:goodshot/view/schedule/dto/schedule.dart';
import 'package:goodshot/view/schedule/http/schedule-api.dart';
import 'package:goodshot/view/schedule/utils/schedule-util.dart';
import 'package:table_calendar/table_calendar.dart';
final GlobalProvider globalProvider = Get.find();
class TableCalendarScreen extends StatefulWidget {
//Future.sync(() => getScheduleList(globalProvider.getUserId()).then((value) => eventList=value));
@override
_TableEventsExampleState createState() => _TableEventsExampleState();
}
class _TableEventsExampleState extends State<TableCalendarScreen> {
Map<DateTime,List<Event>> eventList = Map();
late ValueNotifier<List<Event>> _selectedEvents;
CalendarFormat _calendarFormat = CalendarFormat.month;
RangeSelectionMode _rangeSelectionMode = RangeSelectionMode
.toggledOff; // Can be toggled on/off by longpressing a date
DateTime _focusedDay = DateTime.now();
DateTime? _selectedDay;
DateTime? _rangeStart;
DateTime? _rangeEnd;
@override
void initState() {
Future.sync(() => getScheduleList(globalProvider.getUserId()).then((value) => eventList = value)).then((value) =>{
setState(() {
eventList = value;
_selectedDay = _focusedDay;
_selectedEvents = ValueNotifier(_getEventsForDay(_selectedDay!));
})
}
);
_selectedDay = _focusedDay;
_selectedEvents = ValueNotifier(_getEventsForDay(_selectedDay!));
super.initState();
}
@override
void dispose() {
_selectedEvents.dispose();
super.dispose();
}
List<Event> _getEventsForDay(DateTime day) {
return eventList[DateTime(day.year,day.month,day.day)] ?? [];
}
List<Event> _getEventsForRange(DateTime start, DateTime end) {
// Implementation example
final days = daysInRange(start, end);
return [
for (final d in days) ..._getEventsForDay(d),
];
}
void _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
print('select');
print(eventList);
if (!isSameDay(_selectedDay, selectedDay)) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
_rangeStart = null; // Important to clean those
_rangeEnd = null;
_rangeSelectionMode = RangeSelectionMode.toggledOff;
});
_selectedEvents.value = _getEventsForDay(selectedDay);
}
}
void _onRangeSelected(DateTime? start, DateTime? end, DateTime focusedDay) {
setState(() {
_selectedDay = null;
_focusedDay = focusedDay;
_rangeStart = start;
_rangeEnd = end;
_rangeSelectionMode = RangeSelectionMode.toggledOn;
});
// `start` or `end` could be null
if (start != null && end != null) {
_selectedEvents.value = _getEventsForRange(start, end);
} else if (start != null) {
_selectedEvents.value = _getEventsForDay(start);
} else if (end != null) {
_selectedEvents.value = _getEventsForDay(end);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('굿샷 모임 캘린더'),
),
body: Column(
children: [
TableCalendar<Event>(
firstDay: kFirstDay,
lastDay: kLastDay,
focusedDay: _focusedDay,
selectedDayPredicate: (day) => isSameDay(_selectedDay, day),
rangeStartDay: _rangeStart,
rangeEndDay: _rangeEnd,
calendarFormat: _calendarFormat,
rangeSelectionMode: _rangeSelectionMode,
eventLoader: _getEventsForDay,
startingDayOfWeek: StartingDayOfWeek.monday,
locale: "ko-KR",
headerStyle: HeaderStyle(
formatButtonVisible: false,
titleCentered: true,
),
calendarStyle: CalendarStyle(
// Use `CalendarStyle` to customize the UI
outsideDaysVisible: false,
),
onDaySelected: _onDaySelected,
onRangeSelected: _onRangeSelected,
onFormatChanged: (format) {
if (_calendarFormat != format) {
setState(() {
_calendarFormat = format;
});
}
},
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
},
),
const SizedBox(height: 8.0),
Expanded(
child: ValueListenableBuilder<List<Event>>(
valueListenable: _selectedEvents,
builder: (context, value, _) {
return ListView.builder(
itemCount: value.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('${value[index].groupNo}');
getGroupDetail(value[index].groupNo).then(
(value)=>
{
showDialog(context: context,
builder: (BuildContext context){
return GetGroupScheduleDetailPopup(getGroupItem: value);
})
});
},
title: Text('${value[index]}'),
),
);
},
);
},
),
),
],
),
);
}
}
테이블 위젯을 로드하고 위젯 리스트를 불러온다.
그리고 해당 위젯 리스트는
LinkedHashMap<DateTime,List<Event>>의 형태로 가져온다.
해당 DateTime으로 그룹화를 시킨다.
해당 내용을 지원하는 유틸이다
import 'dart:collection';
import 'package:get/get.dart';
import 'package:goodshot/global-provider.dart';
import 'package:goodshot/view/schedule/dto/schedule.dart';
import 'package:goodshot/view/schedule/http/schedule-api.dart';
import 'package:table_calendar/table_calendar.dart';
/// Example events.
///
/// Using a [LinkedHashMap] is highly recommended if you decide to use a map.
// final events = LinkedHashMap(
// equals: isSameDay,
//
// )..addAll(eventSource(String userId));
//late Map<DateTime,List<Event>> eventList = Map<DateTime,List<Event>>();
Map<DateTime,List<Event>> settingSchedule(String userId) {
late Map<DateTime,List<Event>> eventList = Map();
getScheduleList(userId).then((value)=>{
eventList = value,
});
return eventList;
}
//Map<DateTime,List<Event>> eventList
LinkedHashMap<DateTime, List<Event>> getEventStore(Map<DateTime,List<Event>> eventList) {
LinkedHashMap<DateTime, List<Event>> kEvents = LinkedHashMap<DateTime, List<Event>>(
equals: isSameDay,
hashCode: getHashCode,
)..addAll(eventList);
return kEvents;
}
int getHashCode(DateTime key) {
return key.day * 1000000 + key.month * 10000 + key.year;
}
/// Returns a list of [DateTime] objects from [first] to [last], inclusive.
List<DateTime> daysInRange(DateTime first, DateTime last) {
final dayCount = last.difference(first).inDays + 1;
return List.generate(
dayCount,
(index) => DateTime.utc(first.year, first.month, first.day + index),
);
}
final kToday = DateTime.now();
final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day);
final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day);
나는 연,월,일에 대해서만 해당 값을 리턴하기 때문에 해당값에 대한 것들을 세팅한다.
마지막으로 api 와 dto이다.
DateTime dateOnly(DateTime dateTime) {
if (dateTime.isUtc) {
return DateTime.utc(dateTime.year, dateTime.month, dateTime.day);
} else {
return DateTime(dateTime.year, dateTime.month, dateTime.day);
}
}
Future<Map<DateTime, List<Event>>> getScheduleList(String userId) async{
Iterable l;
List<Event> eventList;
var eventDayMap = <DateTime, List<Event>>{};
var url = Uri.http(backendHost, 'get-schedule',{"userId":userId});
await http.get(url).then((value) =>
{
l = json.decode(value.body),
eventList = List<Event>.from(l.map((model)=> Event.fromJson(model))),
for (var event in eventList) {
(eventDayMap[dateOnly(event.date)] ??= []).add(event),
}
});
return eventDayMap;
}
class Event {
final String title;
final DateTime date;
final int groupNo;
const Event({required this.date, required this.title,required this.groupNo});
@override
String toString() => title;
factory Event.fromJson(dynamic json){
DateTime time = DateTime.parse(json?['date']);
Event event = Event(
title: json?['title'],
groupNo: json?['group_no'],
date: DateTime(time.year,time.month,time.day)
);
return event;
}
}
해당 dto와 api로 값을 세팅하고, 사용하게 된다.
무튼 해당 방식으로 진행이 되고 아래와 같은 결과를 얻게 된다.
소스를 그대로 가져다 쓰면 오류는 안날 것이다
무튼 해당 관련 모듈구현은 끝났다.
소스를 좀 정리하고 다시 올려야겠다.
반응형
'[Mobile] > [Flutter]' 카테고리의 다른 글
[Flutter] FireStore를 활용해 채팅 모듈 구현 [1] (0) | 2023.09.24 |
---|---|
[Flutter] 오류 조치 사항 (0) | 2023.09.23 |
[Flutter] Naver 지도 api (0) | 2023.09.11 |
[Flutter] Boiler Template 적용시 (0) | 2023.09.09 |
[Flutter] Getx로 전역 Provider 설정 (0) | 2023.09.07 |