kalender 0.3.2
kalender: ^0.3.2 copied to clipboard
This Flutter package offers a Calendar Widget featuring integrated Day, MultiDay, and Month views. Moreover, it empowers you to tailor the visual aspects of the calendar widget.
example/lib/main.dart
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:kalender/kalender.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Kalender Example',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
darkTheme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark,
),
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final CalendarController<Event> controller = CalendarController(
calendarDateTimeRange: DateTimeRange(
start: DateTime(2022),
end: DateTime(2022, 12, 31),
));
final CalendarEventsController<Event> eventController =
CalendarEventsController<Event>();
late ViewConfiguration currentConfiguration = viewConfigurations[0];
List<ViewConfiguration> viewConfigurations = [
CustomMultiDayConfiguration(
name: 'Day',
numberOfDays: 1,
startHour: 1,
endHour: 12,
),
CustomMultiDayConfiguration(
name: 'Custom',
numberOfDays: 1,
),
WeekConfiguration(),
WorkWeekConfiguration(),
MonthConfiguration(),
ScheduleConfiguration(),
MultiWeekConfiguration(
numberOfWeeks: 3,
),
];
@override
void initState() {
super.initState();
DateTime now = DateTime.now();
eventController.addEvents([
CalendarEvent(
dateTimeRange: DateTimeRange(
start: now,
end: now.add(const Duration(hours: 1)),
),
eventData: Event(title: 'Event 1'),
),
CalendarEvent(
dateTimeRange: DateTimeRange(
start: now.add(const Duration(hours: 2)),
end: now.add(const Duration(hours: 5)),
),
eventData: Event(title: 'Event 2'),
),
CalendarEvent(
dateTimeRange: DateTimeRange(
start: DateTime(now.year, now.month, now.day),
end: DateTime(now.year, now.month, now.day)
.add(const Duration(days: 2)),
),
eventData: Event(title: 'Event 3'),
),
]);
}
@override
Widget build(BuildContext context) {
final calendar = CalendarView<Event>(
controller: controller,
eventsController: eventController,
viewConfiguration: currentConfiguration,
tileBuilder: _tileBuilder,
multiDayTileBuilder: _multiDayTileBuilder,
scheduleTileBuilder: _scheduleTileBuilder,
components: CalendarComponents(
calendarHeaderBuilder: _calendarHeader,
),
eventHandlers: CalendarEventHandlers(
onEventTapped: _onEventTapped,
onEventChanged: _onEventChanged,
onCreateEvent: _onCreateEvent,
onEventCreated: _onEventCreated,
),
);
return SafeArea(
child: Scaffold(
body: Stack(
children: [
calendar,
Align(
alignment: Alignment.bottomRight,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FilledButton.tonal(
onPressed: () {
controller.animateToDate(DateTime.now());
},
child: const Text('now'),
),
],
),
),
],
),
),
);
}
CalendarEvent<Event> _onCreateEvent(DateTimeRange dateTimeRange) {
return CalendarEvent(
dateTimeRange: dateTimeRange,
eventData: Event(
title: 'New Event',
),
);
}
Future<void> _onEventCreated(CalendarEvent<Event> event) async {
// Add the event to the events controller.
eventController.addEvent(event);
// Deselect the event.
eventController.deselectEvent();
}
Future<void> _onEventTapped(
CalendarEvent<Event> event,
) async {
if (isMobile) {
eventController.selectedEvent == event
? eventController.deselectEvent()
: eventController.selectEvent(event);
}
}
Future<void> _onEventChanged(
DateTimeRange initialDateTimeRange,
CalendarEvent<Event> event,
) async {
if (isMobile) {
eventController.deselectEvent();
}
}
Widget _tileBuilder(
CalendarEvent<Event> event,
TileConfiguration configuration,
) {
final color = event.eventData?.color ?? Colors.blue;
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
margin: EdgeInsets.zero,
elevation: configuration.tileType == TileType.ghost ? 0 : 8,
color: configuration.tileType != TileType.ghost
? color
: color.withAlpha(100),
child: Center(
child: configuration.tileType != TileType.ghost
? Text(event.eventData?.title ?? 'New Event')
: null,
),
);
}
Widget _multiDayTileBuilder(
CalendarEvent<Event> event,
MultiDayTileConfiguration configuration,
) {
final color = event.eventData?.color ?? Colors.blue;
return Card(
margin: const EdgeInsets.symmetric(vertical: 2),
elevation: configuration.tileType == TileType.selected ? 8 : 0,
color: configuration.tileType == TileType.ghost
? color.withAlpha(100)
: color,
child: Center(
child: configuration.tileType != TileType.ghost
? Text(event.eventData?.title ?? 'New Event')
: null,
),
);
}
Widget _scheduleTileBuilder(CalendarEvent<Event> event, DateTime date) {
return DecoratedBox(
decoration: BoxDecoration(
color: event.eventData?.color ?? Colors.blue,
borderRadius: BorderRadius.circular(8),
),
child: Text(event.eventData?.title ?? 'New Event'),
);
}
Widget _calendarHeader(DateTimeRange dateTimeRange) {
return Row(
children: [
DropdownMenu(
onSelected: (value) {
if (value == null) return;
setState(() {
currentConfiguration = value;
});
},
initialSelection: currentConfiguration,
dropdownMenuEntries: viewConfigurations
.map((e) => DropdownMenuEntry(value: e, label: e.name))
.toList(),
),
IconButton.filledTonal(
onPressed: controller.animateToPreviousPage,
icon: const Icon(Icons.navigate_before_rounded),
),
IconButton.filledTonal(
onPressed: controller.animateToNextPage,
icon: const Icon(Icons.navigate_next_rounded),
),
],
);
}
bool get isMobile {
return kIsWeb ? false : Platform.isAndroid || Platform.isIOS;
}
}
class Event {
Event({
required this.title,
this.description,
this.color,
});
/// The title of the [Event].
final String title;
/// The description of the [Event].
final String? description;
/// The color of the [Event] tile.
final Color? color;
}