Appearance topic

Appearance

This is part of the kalender documentation.

What the calendar looks like: event tiles, theming, and replacing the default components. For where tiles are placed rather than how they look, see Layout.

Tile Components

TileComponents is the primary way to control how events look in the calendar. Pass it as tileComponents to MultiDayHeader, MultiDayBody and MonthBody, the header and body widgets of the day, multi-day and month views. See Headers and bodies for passing those to KalenderView.

For schedule views, use ScheduleTileComponents instead (passed via ScheduleBody.tileComponents).

Simple tile

For most apps a plain tileBuilder is all you need:

MultiDayBody(
  tileComponents: TileComponents(
    tileBuilder: (context, event, tileRange) {
      final myEvent = event as Event;
      return Container(
        decoration: BoxDecoration(
          color: myEvent.color ?? Colors.blue,
          borderRadius: BorderRadius.circular(4),
        ),
        padding: const EdgeInsets.all(4),
        child: Text(myEvent.title, style: const TextStyle(color: Colors.white)),
      );
    },
  ),
)

All TileComponents options

Only tileBuilder is required. Every other field defaults to null, which keeps the package's own behavior: overlayTileBuilder, tileWhenDraggingBuilder, feedbackTileBuilder, dropTargetTile, dragAnchorStrategy, resizeDragAnchorStrategy, resizeHandlePositioner, verticalResizeHandle and horizontalResizeHandle.

mergeSemantics, true by default, merges a tile's widgets into one semantics node, the unit a screen reader announces. Set it to false when a tile holds its own buttons or other controls.

resizeHandlePositioner places the resize handles. details carries the tile's geometry and builds the detectors:

TileComponents(
  tileBuilder: (context, event, tileRange) => Container(),
  resizeHandlePositioner: (context, details) => Stack(
    fit: StackFit.expand,
    children: [
      if (details.showStart)
        Positioned(top: 0, left: 0, right: 0, height: 8, child: details.startResizeDetector),
      if (details.showEnd)
        Positioned(bottom: 0, left: 0, right: 0, height: 8, child: details.endResizeDetector),
    ],
  ),
)

ScheduleTileComponents

Schedule tiles take tileBuilder, tileWhenDraggingBuilder, feedbackTileBuilder, dragAnchorStrategy and mergeSemantics. The drop target is a row highlight, see ScheduleComponents.

Advanced tiles with event-tile utilities

For tiles that need to know the exact tapped time or find nearby events, use the provided mixins.

Tip

The calendar handles taps on a tile only when onEventTapped or onEventTappedWithDetail is set. Leave both unset to handle taps in your tile.

DayEventTileUtils (day / multi-day body tiles)
class CustomDayEventTile extends StatelessWidget with DayEventTileUtils {
  @override
  final KalenderEvent event;

  @override
  final KalenderDateTimeRange tileRange;

  const CustomDayEventTile({
    super.key,
    required this.event,
    required this.tileRange,
  });

  Event get myEvent => event as Event;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapUp: (details) {
        // Convert a local tap position into an exact DateTime.
        final tappedTime = dateTimeFromPosition(context, details.localPosition);
        debugPrint('Tapped at: $tappedTime');

        // Find events that overlap a ±15-minute window around this one.
        final nearby = nearbyEvents(
          context,
          before: const Duration(minutes: 15),
          after: const Duration(minutes: 15),
        );
        debugPrint('Found ${nearby.length} nearby events');
      },
      child: Container(
        decoration: BoxDecoration(
          color: myEvent.color ?? Colors.blue,
          borderRadius: BorderRadius.circular(4),
        ),
        padding: const EdgeInsets.all(4),
        child: Text(myEvent.title, style: const TextStyle(color: Colors.white)),
      ),
    );
  }

  // Static factory. Pass directly to TileComponents.tileBuilder.
  static Widget builder(BuildContext context, KalenderEvent event, KalenderDateTimeRange tileRange) =>
      CustomDayEventTile(
        event: event,
        tileRange: tileRange,
      );
}

const dayTileComponents = TileComponents(tileBuilder: CustomDayEventTile.builder);

Month and multi-day header tiles mix in MultiDayEventTileUtils, which has dateFromPosition in place of dateTimeFromPosition.


Theming

By default the calendar follows your app's Material 3 theme: line colors, text styles, and the rest are derived from the ambient ColorScheme and TextTheme.

To change how every calendar in the app looks, register a KalenderThemeData on your theme. Any field you leave out keeps its Material 3 default.

MaterialApp(
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
    extensions: [
      KalenderThemeData(
        hourLinesStyle: HourLinesStyle(thickness: 2),
        timeIndicatorStyle: TimeIndicatorStyle(lineColor: Colors.pink),
      ),
    ],
  ),
)

Theming part of the app

Registering on ThemeData covers every calendar in the app. To theme one of them differently, wrap it in a KalenderTheme:

KalenderTheme(
  data: const KalenderThemeData(
    hourLinesStyle: HourLinesStyle(thickness: 2),
  ),
  child: KalenderView(
    eventsController: DefaultEventsController(),
    kalenderController: KalenderController(viewConfiguration: MultiDayViewConfiguration.week()),
  ),
)

The nearest one wins when they nest, and fields it leaves out fall through to the theme registered on ThemeData, so a scope can change one thing without restating the rest.

A KalenderTheme also reaches the tile that follows a drag.

How a style is resolved

Four layers, most specific first. Each one fills in the fields the layer above it leaves null.

  1. A style passed directly to a widget, which is how a custom builder styles the widget it returns (see Custom Components).
  2. The nearest KalenderTheme above the calendar.
  3. The KalenderThemeData registered on ThemeData.extensions.
  4. The Material 3 defaults.

Note

The widths of the week number column and the timeline are not styles. Set them with MonthBodyComponents.weekNumberWidth or MultiDayBodyComponents.timelineWidth.

Switching themes transitions the calendar's colors along with the rest of the app. A KalenderTheme scope does not animate.

The overflow overlay

The overlay listing a day's events, opened from the +3 button that stands in for events that do not fit or from KalenderController.showDayOverlay, is themed the same way. Its card and close button take Flutter's own CardThemeData and ButtonStyle.

KalenderThemeData(
  multiDayOverlayStyle: MultiDayOverlayStyle(
    cardTheme: CardThemeData(
      color: Colors.white,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
    ),
    closeButtonStyle: IconButton.styleFrom(backgroundColor: Colors.amber),
    // Dims the calendar behind the card. Transparent by default.
    barrierColor: Colors.black54,
    width: 320,
  ),
)

closeButtonStyle merges over the defaults of a filled tonal icon button, so set only the fields you change.

Custom Components

Pass a KalenderComponents object to KalenderView to override the default widget builders.

Note

Every builder receives a BuildContext as its first argument and resolves what it needs from it: styles with KalenderTheme.of(context), and the state of the enclosing calendar with KalenderScope, one accessor per value.

MultiDayComponents
KalenderComponents(
  multiDayComponents: MultiDayComponents(
    headerComponents: MultiDayHeaderComponents(
      dayHeaderBuilder: (context, date) => CustomWidget(),
      weekNumberBuilder: (context, visibleDateTimeRange) => CustomWidget(),
      leftTriggerBuilder: (context, pageWidth) => SizedBox(width: pageWidth / 20),
      rightTriggerBuilder: (context, pageWidth) => SizedBox(width: pageWidth / 20),
      overlayBuilders: OverlayBuilders(
        multiDayPortalOverlayButtonBuilder:
            (context, portalController, numberOfHiddenRows) => SizedBox(),
      ),
    ),
    bodyComponents: MultiDayBodyComponents(
      hourLines: (context, heightPerMinute, timeOfDayRange) => CustomWidget(),
      timeline: (context, heightPerMinute, timeOfDayRange, eventBeingDragged, visibleDateTimeRange) =>
          CustomWidget(),
      // Sizes the timeline column, for example to fit a custom timeline's labels.
      timelineWidth: (context, timeOfDayRange) => 48,
      daySeparator: (context) => CustomWidget(),
      timeIndicator: (context, timeOfDayRange, heightPerMinute, location) => CustomWidget(),
      leftTriggerBuilder: (context, pageWidth) => SizedBox(width: pageWidth / 20),
      rightTriggerBuilder: (context, pageWidth) => SizedBox(width: pageWidth / 20),
      topTriggerBuilder: (context, viewPortHeight) => SizedBox(height: viewPortHeight / 20),
      bottomTriggerBuilder: (context, viewPortHeight) => SizedBox(height: viewPortHeight / 20),
    ),
  ),
)
MonthComponents
KalenderComponents(
  monthComponents: MonthComponents(
    headerComponents: MonthHeaderComponents(
      weekDayHeaderBuilder: (context, date) => SizedBox(),
    ),
    bodyComponents: MonthBodyComponents(
      monthDayHeaderBuilder: (context, date) => SizedBox(),
      // Custom per-cell background, or use the ready-made
      // MonthDayCell.shadeAdjacentMonths() to shade adjacent-month days.
      monthDayCellBuilder: (context, details) => SizedBox(),
      monthGridBuilder: (context, numberOfRows) => SizedBox(),
      weekNumberBuilder: (context, visibleDateTimeRange) => SizedBox(),
      leftTriggerBuilder: (context, pageWidth) => SizedBox(),
      rightTriggerBuilder: (context, pageWidth) => SizedBox(),
      overlayBuilders: OverlayBuilders(
        multiDayPortalOverlayButtonBuilder:
            (context, portalController, numberOfHiddenRows) => SizedBox(),
      ),
    ),
  ),
)
ScheduleComponents
KalenderComponents(
  scheduleComponents: ScheduleComponents(
    // The date column shown beside the first row of each day.
    leadingDateBuilder: (context, date) => Container(),

    // Wraps a row to highlight it as the drop target during a drag.
    scheduleTileHighlightBuilder: (context, date, range, child) =>
        Container(child: child),

    // Optional: builder for days with no events.
    emptyItemBuilder: (context, tileRange) => Container(),

    // Optional: builder for the month heading rows.
    monthItemBuilder: (context, monthRange) => Container(),
  ),
)

Classes

DayHeader Appearance
A widget that displays the name of the day and the day number of the week.
DayHeaderStyle Appearance
The style for the DayHeader.
DayNumberStyle Appearance
The style of the DayNumber.
DaySeparator Appearance
A widget that displays a separator between days.
DaySeparatorStyle Appearance
The style for the DaySeparator widget.
HourLines Appearance
A widget that displays lines for each hour based on the timeOfDayRange and heightPerMinute.
HourLinesStyle Appearance
The style of the HourLines widget.
KalenderComponents Appearance
A class holding the widget builders used by the KalenderView.
KalenderTheme Appearance
Applies a KalenderThemeData to the calendars below it.
KalenderThemeData Appearance
The calendar's visual theme, following the same layering as Flutter's own component themes.
MonthBodyComponents Appearance
The component builders used by the MonthBody.
MonthComponents Appearance
A class containing custom widget builders for the MonthBody and MonthHeader.
MonthDayCell Appearance
Renders the background of a single day cell in the month body.
MonthDayCellDetails Appearance
Details describing a single day cell, passed to a MonthDayCellBuilder.
MonthDayHeader Appearance
A widget that displays the day number.
MonthDayHeaderStyle Appearance
The style of the MonthDayHeader.
MonthGrid Appearance
A widget that displays the month grid.
MonthGridStyle Appearance
The style of the MonthGrid.
MonthHeaderComponents Appearance
The component builders used by the MonthHeader.
MultiDayBodyComponents Appearance
The component builders used by the MultiDayBody.
MultiDayComponents Appearance
A class containing custom widget builders for the MultiDayBody and MultiDayHeader.
MultiDayEventOverlayTile Appearance
MultiDayHeaderComponents Appearance
The component builders used by the MultiDayHeader.
MultiDayOverlay Appearance
MultiDayOverlayPortal Appearance
The "+N more" button of a day. It opens the day's overlay through KalenderController.openDayOverlay.
MultiDayOverlayStyle Appearance
MultiDayPortalOverlayButton Appearance
MultiDayPortalOverlayButtonStyle Appearance
OverlayBuilders Appearance
Builders used to create the overlayPortal, overlay and overlay button widgets.
ResizeHandleStyle Appearance
The style of the resize handles laid out by DefaultResizeHandles.
ScheduleComponents Appearance
A class containing custom widget builders for the ScheduleBody.
ScheduleDate Appearance
The short day name and the day of the month shown at the start of each day in the schedule.
ScheduleDateStyle Appearance
The style of the ScheduleDate.
ScheduleTileComponents Appearance
The components used by the ScheduleBody to render the event tiles.
ScheduleTileHighlight Appearance
A widget that highlights the list item if the date is within the given range.
ScheduleTileHighlightStyle Appearance
TileComponents Appearance
The components used by the MultiDayBody/MonthBody to render the event tiles.
TimeIndicator Appearance
A widget that displays the current time as a line and a circle.
TimeIndicatorStyle Appearance
The style of the TimeIndicator widget.
TimeLine Appearance
A widget that displays a list of times based on the timeOfDayRange and heightPerMinute.
TimelineStyle Appearance
The style of the TimeLine widget.
WeekDayHeader Appearance
A widget that displays the name of the day of the week.
WeekDayHeaderStyle Appearance
The style of the WeekDayHeader.
WeekNumber Appearance
A widget that displays the week number.
WeekNumberStyle Appearance
The style of the WeekNumber.

Mixins

DayEventTileUtils Appearance
Utilities for a tile built by TileComponents.tileBuilder in a day-based view.
EventTileUtils Appearance
MultiDayEventTileUtils Appearance
Utilities for a tile that represents an event spanning several days, in the month view or the multi-day header.
TimeLineUtils Appearance
A mixin that provides utility methods for the TimeLine and HourLines widget.

Extensions

KalenderLocale on BuildContext Appearance
Gives a string builder access to the locale of the calendar it is building for.

Constants

kDefaultWeekNumberWidth → const double Appearance
The width defaultWeekNumberWidth returns when the style sets none.

Typedefs

DateStringBuilder = String Function(BuildContext context, DateTime date) Appearance
Builds the text displayed for date.
DayHeaderBuilder = Widget Function(BuildContext context, DateTime date) Appearance
The day header builder.
DaySeparatorBuilder = Widget Function(BuildContext context) Appearance
The day separator builder.
EmptyItemBuilder = Widget Function(BuildContext context, KalenderDateTimeRange tileRange) Appearance
The builder for the empty item.
FeedbackTileBuilder = Widget Function(BuildContext context, KalenderEvent event, Size dropTargetWidgetSize) Appearance
The builder for the feedback tile. (When dragging)
HiddenEventCountStringBuilder = String Function(BuildContext context, int numberOfHiddenEvents) Appearance
Builds the text displayed on the overlay button that opens the hidden events.
HourLinesBuilder = Widget Function(BuildContext context, double heightPerMinute, KalenderTimeRange timeOfDayRange) Appearance
The hour lines builder.
KalenderTimeStringBuilder = String Function(BuildContext context, KalenderTime time) Appearance
Builds the text displayed for time.
MonthDayCellBuilder = Widget Function(BuildContext context, MonthDayCellDetails details) Appearance
Builds the background of a single day cell in the month body.
MonthDayHeaderBuilder = Widget Function(BuildContext context, DateTime date) Appearance
The month day header builder.
MonthGridBuilder = Widget Function(BuildContext context, int numberOfRows) Appearance
The month grid builder.
MonthItemBuilder = Widget Function(BuildContext context, KalenderDateTimeRange tileRange) Appearance
The builder for the month item.
MultiDayOverlayBuilder = Widget Function(BuildContext context, {required DateTime date, required List<KalenderEvent> events, required RenderBoxCallback getMultiDayEventLayoutRenderBox, required RenderBoxCallback getOverlayPortalRenderBox, required MultiDayOverlayEventTileBuilder overlayTileBuilder, required OverlayPortalController portalController, required double tileHeight}) Appearance
A function that returns a MultiDayOverlay widget.
MultiDayOverlayEventTileBuilder = MultiDayEventOverlayTile Function(BuildContext context, KalenderEvent event, FloatingDateTimeRange floatingRange, VoidCallback dismissOverlay) Appearance
A function that returns a MultiDayEventOverlayTile for the multi-day overlay.
MultiDayOverlayPortalBuilder = Widget Function(BuildContext context, {required DateTime date, required List<KalenderEvent> events, required int numberOfHiddenRows, required OverlayBuilders? overlayBuilders, required double tileHeight}) Appearance
A function that returns a MultiDayOverlayPortal.
MultiDayPortalOverlayButtonBuilder = Widget Function(BuildContext context, OverlayPortalController portalController, int numberOfHiddenRows) Appearance
The builder used to create the button for the MultiDayPortalOverlayButton.
ScheduleDateBuilder = Widget Function(BuildContext context, FloatingDateTime date) Appearance
Builds the date shown at the start of each day in the schedule.
ScheduleTileHighlightBuilder = Widget Function(BuildContext context, FloatingDateTime date, ValueNotifier<FloatingDateTimeRange?> range, Widget child) Appearance
The schedule tile highlight builder.
TileBuilder = Widget Function(BuildContext context, KalenderEvent event, KalenderDateTimeRange tileRange) Appearance
The default builder for the event tiles.
TileDropTargetBuilder = Widget Function(BuildContext context, KalenderEvent event) Appearance
The builder for the drop target event tile.
TileWhenDraggingBuilder = Widget Function(BuildContext context, KalenderEvent event) Appearance
The builder for the event tile when dragging.
TimeIndicatorBuilder = Widget Function(BuildContext context, KalenderTimeRange timeOfDayRange, double heightPerMinute, Location? location) Appearance
The time indicator builder.
TimeLineBuilder = Widget Function(BuildContext context, double heightPerMinute, KalenderTimeRange timeOfDayRange, ValueNotifier<KalenderEvent?> eventBeingDragged, ValueListenable<KalenderDateTimeRange> visibleDateTimeRange) Appearance
The time line builder.
TimelineWidthBuilder = double Function(BuildContext context, KalenderTimeRange timeOfDayRange) Appearance
Resolves the width of the timeline gutter.
WeekDayHeaderBuilder = Widget Function(BuildContext context, DateTime date) Appearance
The week day header builder.
WeekNumberBuilder = Widget Function(BuildContext context, KalenderDateTimeRange visibleDateTimeRange) Appearance
The week number builder.
WeekNumberWidthBuilder = double Function(BuildContext context) Appearance
Resolves the width of the month's week number column.