Flutter hourly calendar
Flutter hourly calendar. Visualizes your event according to the selected time of day
Screenshots
![]() |
![]() |
![]() |
![]() |
Usage
HourlyCalendar(
controller: controller,
onSelected: (selectedItem, controller) {
print("${selectedItem.startTime} - ${selectedItem.endTime}");
},
),
var random = math.Random();
late var items = List.generate(20, (index) {
return CalendarData<String>(
title: "Event $index",
id: "$index",
startTime: DateTime.now().add(const Duration(days: -5)).add(Duration(days: index)).copyWith(
hour: random.nextInt(20) - 10,
minute: random.nextInt(59),
),
endTime: DateTime.now().add(const Duration(days: -5)).add(Duration(days: index)).copyWith(
hour: random.nextInt(23) + 12,
minute: random.nextInt(59),
),
data: "event $index",
color: Color((math.Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0));
});
late final HourlyCalendarController controller = HourlyCalendarController(items, date: DateTime.now());
Params
HourlyCalendarController
-
List<CalendarData<T>> items, {this.oneHourHeight = 40, DateTime? date} -
items: your events. TypeList<CalendarData<T>> -
oneHourHeight: 1 hour total height.All calculations are based on this value
double _findHeight(DateTime start, DateTime end) {
// total height of on second
var perSecondHeight = controller.oneHourHeight / 3600;
var diff = start.difference(end);
// total event seconds
var totalSecond = diff.inSeconds;
// total event height
return (totalSecond * perSecondHeight).toDouble().abs();
}
date : selected calendar date. default is DateTime.now()
HourlyCalendar
-
controller [HourlyCalendarController]calender controller. You must specify your events in the controller. -
mainContainerDecoration-[BoxDecoration]main container decoration -
hourContainerDecoration-[BoxDecoration]container decoration each hour -
hourTextStyle- TextStyle text style each hour -
bottomListTitleStyle- TextStyle footer list text style -
bottomListHourStyle- TextStyle footer list duration style -
controller- HourlyCalendarController calendar controller -
hideHeader- bool hide header if istrue -
hideFooter- bool hide footer if istrue -
headerHeight- double header height -
hoursWidth- double hours width -
headerDateTextStyle- TextStyle header text style -
headerDateFormat- String header date text date format -
hourBuilder- build each hour
(context,hour) => Container(
padding: const EdgeInsets.all(8),
decoration: hourContainerDecoration ??
BoxDecoration(
border: Border(
right: BorderSide(color: Theme.of(context).disabledColor.withOpacity(0.5)),
),
),
child: Center(
child: Text(
hour.text,
style: hourTextStyle ??
Theme.of(context).textTheme.bodyLarge!.copyWith(
fontSize: 15,
color: hour.isShift
? Theme.of(context).disabledColor.withOpacity(0.3)
: Theme.of(context).disabledColor,
),
),
),
)
itemBuilder-> build each event
(context,item,controller,selectedId) => InkWell(
onLongPress: () {
controller.setSelected(item.id);
if (onSelected != null) {
onSelected!(item, controller);
}
},
onTap: () => controller.setSelected(item.id),
child: Container(
// width: 100,
height: mainContainerHeight,
decoration: BoxDecoration(
color: selectedId == item.id ? item.color : item.color.withAlpha(150),
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: RotatedBox(
quarterTurns: 1,
child: FittedBox(
child: Text(
item.title,
style: hourTextStyle ??
Theme.of(context).textTheme.bodyLarge!.copyWith(
fontSize: 15,
color: Colors.white,
),
),
),
),
),
),
);
bottomItemListBuilder-> build bottom event list
(context,item,controller,selectedId)=>Row(children:[
Text(item.startTime),
Text(item.endTime),
])
-
onSelected- onClicked Event(selectedItem,controller) => void -
onRefresh- onRefresh Event() => void -
headerBuilder- header builder
(date,controller)=>Row(
children:[
Button(onPress:controller.previousDate,text:'Previous'),
Expanded(child: Text(date.toString().format("HH:mm")),)
Button(onPress:controller.nextDate,text:'Next')
])
```



