📅 Customizable, animated calendar widget including day & week views.
Event positioning demo | Dark mode & custom range |
---|---|
1. Initialize time_machine
This package uses time_machine for handling date and time, which you first have to initialize.
Add this to your pubspec.yaml
:
flutter:
assets:
- packages/time_machine/data/cultures/cultures.bin
- packages/time_machine/data/tzdb/tzdb.bin
Modify your main.dart
's main()
:
import 'package:flutter/services.dart';
import 'package:time_machine/time_machine.dart';
void main() async {
// Call these two functions before `runApp()`.
WidgetsFlutterBinding.ensureInitialized();
await TimeMachine.initialize({'rootBundle': rootBundle});
runApp(MyApp());
}
Source: https://pub.dev/packages/time_machine#flutter-specific-notes
2. Define your Event
s
Events are provided as instances of Event
. To get you started, there's the subclass BasicEvent
, which you can instantiate directly. If you want to be more specific, you can also implement your own class extending Event
.
Note: Most classes of timetable accept a type-parameter
E extends Event
. Please set it to your chosenEvent
-subclass (e.g.BasicEvent
) to avoid runtime exceptions.
In addition, you also need a Widget
to display your events. When using BasicEvent
, this can simply be BasicEventWidget
.
3. Create an EventProvider
As the name suggests, you use EventProvider
to provide Event
s to timetable. There are currently two EventProvider
s to choose from:
EventProvider.list(List<E> events)
: If you have a non-changing list of events.EventProvider.simpleStream(Stream<List<E>> eventStream)
: If you have a limited, changing list of events.EventProvider.stream({StreamedEventGetter<E> eventGetter})
: If your events can change or you have many events and only want to load the relevant subset.
final myEventProvider = EventProvider.list([
BasicEvent(
id: 0,
title: 'My Event',
color: Colors.blue,
start: LocalDate.today().at(LocalTime(13, 0, 0)),
end: LocalDate.today().at(LocalTime(15, 0, 0)),
),
]);
For trying out the behavior of changing events, you can create a StreamController<List<E>>
and add()
different lists of events, e.g. in Future.delayed()
:
final eventController = StreamController<List<BasicEvent>>()..add([]);
final provider = EventProvider.simpleStream(eventController.stream);
Future.delayed(Duration(seconds: 5), () => eventController.add(/* some events */));
// Don't forget to close the stream controller when you're done, e.g. in `dispose`:
eventController.close();
See the example for more
EventProvider
samples!
4. Create a TimetableController
Similar to a ScrollController
or a TabController
, a TimetableController
is responsible for interacting with a Timetable
and managing its state. You can instantiate it with your EventProvider
:
final myController = TimetableController(
eventProvider: myEventProvider,
// Optional parameters with their default values:
initialTimeRange: InitialTimeRange.range(
startTime: LocalTime(8, 0, 0),
endTime: LocalTime(20, 0, 0),
),
initialDate: LocalDate.today(),
visibleRange: VisibleRange.week(),
firstDayOfWeek: DayOfWeek.monday,
);
Don't forget to
dispose
your controller, e.g. inState.dispose
!
5. Create your Timetable
Using your TimetableController
, you can now create a Timetable
widget:
Timetable<BasicEvent>(
controller: myController,
eventBuilder: (event) => BasicEventWidget(event),
allDayEventBuilder: (context, event, info) =>
BasicAllDayEventWidget(event, info: info),
)
And you're done 🎉
For a full list of visual properties that can be tweaked, see TimetableThemeData
.
To apply a theme, specify it in the Timetable
constructor:
Timetable<BasicEvent>(
controller: /* ... */,
theme: TimetableThemeData(
primaryColor: Colors.teal,
partDayEventMinimumDuration: Period(minutes: 30),
// ...and many more!
),
),
- Smartly arrange overlapping events
- Zooming
- Selectable
VisibleRange
s - Display all-day events at the top
- Theming
- Animate between different
VisibleRange
s - Month-view, Agenda-view
- Listener when tapping the background (e.g. for creating an event)
- Support for event resizing