From 7181614161cf5465bd29e3a2d113fccfd5185fa6 Mon Sep 17 00:00:00 2001 From: lavigarg-simform Date: Tue, 26 May 2026 12:44:26 +0530 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20MultiDay=20View=20option=20to?= =?UTF-8?q?=20web=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 + doc/documentation.md | 40 ++++ example/lib/enumerations.dart | 2 +- example/lib/pages/multi_day_view_page.dart | 2 +- example/lib/widgets/calendar_configs.dart | 3 + example/lib/widgets/calendar_views.dart | 5 +- .../lib/widgets/multi_day_view_widget.dart | 2 +- lib/src/calendar_event_data.dart | 11 +- .../_internal_multi_day_view_page.dart | 116 +++++------ lib/src/multi_day_view/multi_day_view.dart | 180 ++++++++---------- 10 files changed, 203 insertions(+), 162 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa0dec09..f00c5bcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# [Unreleased - 26 May 2026] + +- Added `weekTitleBackgroundColor` to `MultiDayView` to customize the week title background color. + # [Unreleased - 11 May 2026] - Fixed `MonthViewBuilder` to be generic for improved type safety in `MonthView`. [#524](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/524) diff --git a/doc/documentation.md b/doc/documentation.md index 4c8e1491..5a05414b 100644 --- a/doc/documentation.md +++ b/doc/documentation.md @@ -476,6 +476,7 @@ MultiDayView( // Multi-day configuration daysInView: 3, // Number of days to display (default is 3) weekTitleHeight: 50, // Height of week day title + weekTitleBackgroundColor: Colors.grey.shade200, // Background color of week title showVerticalLines: true, // Show the vertical line between days showWeekDayAtBottom: false, // Show week day at bottom position showLiveTimeLineInAllDays: true, // Display live time line in all pages @@ -1051,6 +1052,45 @@ MonthView( * Use `monthViewStyle.showWeekTileBorder` to control week day title border visibility * Use `monthViewBuilders.headerBuilder` to customize or completely replace the month header +### MultiDay View +* To customise week number & weekdays use `weekNumberBuilder` & `weekDayBuilder`. +* Default week day tile color is `multiDayTileColor` in `MultiDayViewThemeData` (defaults to `surfaceContainerHigh`). + * Use `weekTitleBackgroundColor` to override it per-widget. +* Default page background color is `pageBackgroundColor` in `MultiDayViewThemeData` (defaults to `surfaceContainerLowest`). + * Use `backgroundColor` to override it per-widget. +* Default timeline text color is `timelineTextColor` in `MultiDayViewThemeData` (defaults to `onSurface`). + * Use `markingStyle` in `DefaultTimeLineMark` to give text style, or `timeLineBuilder` to fully replace the timeline. +* Default live time indicator color is `liveIndicatorColor` in `MultiDayViewThemeData` (defaults to `primary`). + * Use `liveTimeIndicatorSettings` to customise it per-widget. +* Default hour/half hour/quarter hour line color is `hourLineColor` / `halfHourLineColor` / `quarterHourLineColor` in `MultiDayViewThemeData` (all default to `surfaceContainerHighest`). + * Use `hourIndicatorSettings`, `halfHourIndicatorSettings`, and `quarterHourIndicatorSettings` to customise per-widget. +* Default vertical line color between days is `verticalLinesColor` in `MultiDayViewThemeData`. +* To customise the divider between weekdays and full-day events use `dividerSettings`. + +```dart + hourIndicatorSettings: HourIndicatorSettings( + color: Colors.greenAccent, + lineStyle: LineStyle.dashed, + ), + showHalfHours: true, + halfHourIndicatorSettings: HourIndicatorSettings( + color: Colors.redAccent, + lineStyle: LineStyle.dashed, + ), + dividerSettings: DividerSettings( + thickness: 2, + height: 2, + color: Colors.blueAccent, + indent: 10, + endIndent: 10, + ), +``` + +Hide divider in multiday view. +```dart + dividerSettings: DividerSettings.none(), +``` + # Migration Guides ## Migrate from `1.x.x` to latest diff --git a/example/lib/enumerations.dart b/example/lib/enumerations.dart index 0cb3c76b..c14950ee 100644 --- a/example/lib/enumerations.dart +++ b/example/lib/enumerations.dart @@ -1 +1 @@ -enum CalendarView { month, day, week } +enum CalendarView { month, day, week, multiday } diff --git a/example/lib/pages/multi_day_view_page.dart b/example/lib/pages/multi_day_view_page.dart index 00b9023b..be48ce1a 100644 --- a/example/lib/pages/multi_day_view_page.dart +++ b/example/lib/pages/multi_day_view_page.dart @@ -18,7 +18,7 @@ class _MultiDayViewDemoState extends State { @override Widget build(BuildContext context) { return ResponsiveWidget( - webWidget: WebHomePage(selectedView: CalendarView.week), + webWidget: WebHomePage(selectedView: CalendarView.multiday), mobileWidget: Scaffold( primary: false, appBar: AppBar(leading: const SizedBox.shrink()), diff --git a/example/lib/widgets/calendar_configs.dart b/example/lib/widgets/calendar_configs.dart index 7079de84..632bd129 100644 --- a/example/lib/widgets/calendar_configs.dart +++ b/example/lib/widgets/calendar_configs.dart @@ -126,6 +126,9 @@ class _CalendarConfigState extends State { case CalendarView.week: viewName = translate.weekView; break; + case CalendarView.multiday: + viewName = translate.multidayView; + break; } return GestureDetector( onTap: () => widget.onViewChange(view), diff --git a/example/lib/widgets/calendar_views.dart b/example/lib/widgets/calendar_views.dart index 7988893e..fea4dcc9 100644 --- a/example/lib/widgets/calendar_views.dart +++ b/example/lib/widgets/calendar_views.dart @@ -6,6 +6,7 @@ import '../enumerations.dart'; import '../theme/app_colors.dart'; import 'day_view_widget.dart'; import 'month_view_widget.dart'; +import 'multi_day_view_widget.dart'; import 'week_view_widget.dart'; class CalendarViews extends StatelessWidget { @@ -29,7 +30,9 @@ class CalendarViews extends StatelessWidget { ? MonthViewWidget(width: width) : view == CalendarView.day ? DayViewWidget(width: width) - : WeekViewWidget(width: width), + : view == CalendarView.week + ? WeekViewWidget(width: width) + : MultiDayViewWidget(width: width), ), ); } diff --git a/example/lib/widgets/multi_day_view_widget.dart b/example/lib/widgets/multi_day_view_widget.dart index fb812969..01efa964 100644 --- a/example/lib/widgets/multi_day_view_widget.dart +++ b/example/lib/widgets/multi_day_view_widget.dart @@ -16,7 +16,7 @@ class MultiDayViewWidget extends StatelessWidget { daysInView: 3, width: width, showLiveTimeLineInAllDays: true, - eventArranger: SideEventArranger(maxWidth: 30), + eventArranger: SideEventArranger(), timeLineWidth: 65, scrollPhysics: const BouncingScrollPhysics(), liveTimeIndicatorSettings: LiveTimeIndicatorSettings( diff --git a/lib/src/calendar_event_data.dart b/lib/src/calendar_event_data.dart index f898a373..f60e1c57 100644 --- a/lib/src/calendar_event_data.dart +++ b/lib/src/calendar_event_data.dart @@ -6,9 +6,8 @@ import 'package:flutter/material.dart'; import '../calendar_view.dart'; -@immutable - /// Stores metadata for a calendar event and its date/time boundaries. +@immutable class CalendarEventData { /// Specifies date on which all these events are. final DateTime date; @@ -112,10 +111,10 @@ class CalendarEventData { /// [currentDate] or not. /// bool occursOnDate(DateTime currentDate) { - return currentDate == date || - currentDate == endDate || - (currentDate.isBefore(endDate.withoutTime) && - currentDate.isAfter(date.withoutTime)); + return currentDate.compareWithoutTime(date) || + currentDate.compareWithoutTime(endDate) || + (currentDate.withoutTime.isBefore(endDate) && + currentDate.withoutTime.isAfter(date)); } /// Returns event data in [Map] format. diff --git a/lib/src/multi_day_view/_internal_multi_day_view_page.dart b/lib/src/multi_day_view/_internal_multi_day_view_page.dart index 3be0f648..2732a3d4 100644 --- a/lib/src/multi_day_view/_internal_multi_day_view_page.dart +++ b/lib/src/multi_day_view/_internal_multi_day_view_page.dart @@ -91,6 +91,9 @@ class InternalMultiDayViewPage extends StatefulWidget { /// Height of week title. final double weekTitleHeight; + /// Background color of week title + final Color? weekTitleBackgroundColor; + /// Width of week title. final double weekTitleWidth; @@ -174,59 +177,64 @@ class InternalMultiDayViewPage extends StatefulWidget { /// This method will be called when user taps on timestamp in timeline. final TimestampCallback? onTimestampTap; + /// Background color of the calendar page. + final Color? backgroundColor; + /// A single page for week view. - const InternalMultiDayViewPage( - {Key? key, - required this.showVerticalLine, - required this.weekTitleHeight, - required this.weekDayBuilder, - required this.weekNumberBuilder, - required this.width, - required this.dates, - required this.eventTileBuilder, - required this.controller, - required this.timeLineBuilder, - required this.hourIndicatorSettings, - required this.hourLinePainter, - required this.halfHourIndicatorSettings, - required this.quarterHourIndicatorSettings, - required this.dividerSettings, - required this.showLiveLine, - required this.liveTimeIndicatorSettings, - required this.heightPerMinute, - required this.timeLineWidth, - required this.timeLineOffset, - required this.height, - required this.hourHeight, - required this.eventArranger, - required this.verticalLineOffset, - required this.weekTitleWidth, - required this.onTileTap, - required this.onTileLongTap, - required this.onDateLongPress, - required this.onDateTap, - required this.weekDays, - required this.minuteSlotSize, - required this.scrollConfiguration, - required this.startHour, - required this.fullDayEventBuilder, - required this.weekDetectorBuilder, - required this.showWeekDayAtBottom, - required this.showHalfHours, - required this.showQuarterHours, - required this.emulateVerticalOffsetBy, - required this.onTileDoubleTap, - required this.endHour, - required this.onTimestampTap, - this.fullDayHeaderTitle = '', - required this.fullDayHeaderTextConfig, - required this.scrollPhysics, - required this.scrollListener, - required this.multiDayViewScrollController, - this.lastScrollOffset = 0.0, - this.keepScrollOffset = false, - this.showMutliDayBottomLine = true}) - : super(key: key); + const InternalMultiDayViewPage({ + Key? key, + required this.showVerticalLine, + required this.weekTitleHeight, + required this.weekDayBuilder, + required this.weekNumberBuilder, + required this.width, + required this.dates, + required this.eventTileBuilder, + required this.controller, + required this.timeLineBuilder, + required this.hourIndicatorSettings, + required this.hourLinePainter, + required this.halfHourIndicatorSettings, + required this.quarterHourIndicatorSettings, + required this.dividerSettings, + required this.showLiveLine, + required this.liveTimeIndicatorSettings, + required this.heightPerMinute, + required this.timeLineWidth, + required this.timeLineOffset, + required this.height, + required this.hourHeight, + required this.eventArranger, + required this.verticalLineOffset, + required this.weekTitleWidth, + required this.weekTitleBackgroundColor, + required this.onTileTap, + required this.onTileLongTap, + required this.onDateLongPress, + required this.onDateTap, + required this.weekDays, + required this.minuteSlotSize, + required this.scrollConfiguration, + required this.startHour, + required this.fullDayEventBuilder, + required this.weekDetectorBuilder, + required this.showWeekDayAtBottom, + required this.showHalfHours, + required this.showQuarterHours, + required this.emulateVerticalOffsetBy, + required this.onTileDoubleTap, + required this.endHour, + required this.onTimestampTap, + required this.fullDayHeaderTextConfig, + required this.scrollPhysics, + required this.scrollListener, + required this.multiDayViewScrollController, + this.backgroundColor, + this.fullDayHeaderTitle = '', + this.lastScrollOffset = 0.0, + this.keepScrollOffset = false, + this.showMutliDayBottomLine = true, + }) : super(key: key); @override _InternalMultiDayViewPageState createState() => @@ -280,6 +288,7 @@ class _InternalMultiDayViewPageState final direction = Directionality.of(context); return Container( + color: widget.backgroundColor ?? themeColor.pageBackgroundColor, height: widget.height + widget.weekTitleHeight, width: widget.width, child: Column( @@ -289,7 +298,8 @@ class _InternalMultiDayViewPageState crossAxisAlignment: CrossAxisAlignment.end, children: [ ColoredBox( - color: themeColor.headerBackgroundColor, + color: + widget.weekTitleBackgroundColor ?? themeColor.multiDayTileColor, child: SizedBox( width: widget.width, child: Row( diff --git a/lib/src/multi_day_view/multi_day_view.dart b/lib/src/multi_day_view/multi_day_view.dart index 1787f950..45d07bca 100644 --- a/lib/src/multi_day_view/multi_day_view.dart +++ b/lib/src/multi_day_view/multi_day_view.dart @@ -117,6 +117,9 @@ class MultiDayView extends StatefulWidget { /// Height of week day title, final double weekTitleHeight; + /// Background color of week title + final Color? weekTitleBackgroundColor; + /// Builder to build week day. final DateWidgetBuilder? weekDayBuilder; @@ -236,6 +239,7 @@ class MultiDayView extends StatefulWidget { this.weekPageHeaderBuilder, this.eventArranger, this.weekTitleHeight = 50, + this.weekTitleBackgroundColor, this.weekDayBuilder, this.weekNumberBuilder, this.backgroundColor, @@ -423,7 +427,6 @@ class MultiDayViewState extends State> { widget.maxDay != oldWidget.maxDay) { _setDateRange(); _regulateCurrentDate(); - // updateRange(); _pageController.jumpToPage(_currentIndex); } @@ -523,91 +526,81 @@ class MultiDayViewState extends State> { _currentEndDate, ), Expanded( - child: DecoratedBox( - decoration: BoxDecoration(color: widget.backgroundColor), - child: SizedBox( - height: _height, - width: _width, - child: PageView.builder( - itemCount: _totalWeeks, - controller: _pageController, - physics: widget.pageViewPhysics, - onPageChanged: _onPageChange, - itemBuilder: (_, index) { - // final dates = DateTime(_minDate.year, _minDate.month, - // _minDate.day + (index * DateTime.daysPerWeek)) - // .datesOfWeek( - // start: widget.startDay, - // showWeekEnds: widget.showWeekends, - // ); - - final dates = _minDate.getMultiDateRangeList( - _minDate.withoutTime, index, - daysInView: widget.daysInView); - - return ValueListenableBuilder( - valueListenable: _scrollConfiguration, - builder: (_, __, ___) => InternalMultiDayViewPage( - key: ValueKey(dates[0].toString()), - height: _height, - width: _width, - weekTitleWidth: _weekTitleWidth, - weekTitleHeight: widget.weekTitleHeight, - weekDayBuilder: _weekDayBuilder, - weekNumberBuilder: _weekNumberBuilder, - weekDetectorBuilder: _weekDetectorBuilder, - liveTimeIndicatorSettings: - _liveTimeIndicatorSettings, - timeLineBuilder: _timeLineBuilder, - onTimestampTap: widget.onTimestampTap, - onTileTap: widget.onEventTap, - onTileLongTap: widget.onEventLongTap, - onDateLongPress: widget.onDateLongPress, - onDateTap: widget.onDateTap, - onTileDoubleTap: widget.onEventDoubleTap, - eventTileBuilder: _eventTileBuilder, - heightPerMinute: widget.heightPerMinute, - hourIndicatorSettings: _hourIndicatorSettings, - hourLinePainter: _hourLinePainter, - halfHourIndicatorSettings: - _halfHourIndicatorSettings, - quarterHourIndicatorSettings: - _quarterHourIndicatorSettings, - dividerSettings: _dividerSettings, - dates: dates, - showLiveLine: widget.showLiveTimeLineInAllDays || - _showLiveTimeIndicator(dates), - timeLineOffset: widget.timeLineOffset, - timeLineWidth: _timeLineWidth, - verticalLineOffset: 0, - showVerticalLine: widget.showVerticalLines, - controller: controller, - hourHeight: _hourHeight, - multiDayViewScrollController: _scrollController, - eventArranger: _eventArranger, - showMutliDayBottomLine: - widget.showWeekDayBottomLine, - weekDays: _weekDays, - minuteSlotSize: widget.minuteSlotSize, - scrollConfiguration: _scrollConfiguration, - fullDayEventBuilder: _fullDayEventBuilder, - startHour: _startHour, - showHalfHours: widget.showHalfHours, - showQuarterHours: widget.showQuarterHours, - emulateVerticalOffsetBy: - widget.emulateVerticalOffsetBy, - showWeekDayAtBottom: widget.showWeekDayAtBottom, - endHour: _endHour, - fullDayHeaderTitle: _fullDayHeaderTitle, - fullDayHeaderTextConfig: _fullDayHeaderTextConfig, - lastScrollOffset: _lastScrollOffset, - scrollPhysics: widget.scrollPhysics, - scrollListener: _scrollPageListener, - keepScrollOffset: widget.keepScrollOffset, - ), - ); - }, - ), + child: SizedBox( + height: _height, + width: _width, + child: PageView.builder( + itemCount: _totalWeeks, + controller: _pageController, + physics: widget.pageViewPhysics, + onPageChanged: _onPageChange, + itemBuilder: (_, index) { + final dates = _minDate.getMultiDateRangeList( + _minDate.withoutTime, index, + daysInView: widget.daysInView); + + return ValueListenableBuilder( + valueListenable: _scrollConfiguration, + builder: (_, __, ___) => InternalMultiDayViewPage( + key: ValueKey(dates[0].toString()), + height: _height, + width: _width, + weekTitleWidth: _weekTitleWidth, + weekTitleHeight: widget.weekTitleHeight, + weekTitleBackgroundColor: + widget.weekTitleBackgroundColor, + weekDayBuilder: _weekDayBuilder, + weekNumberBuilder: _weekNumberBuilder, + weekDetectorBuilder: _weekDetectorBuilder, + liveTimeIndicatorSettings: _liveTimeIndicatorSettings, + timeLineBuilder: _timeLineBuilder, + onTimestampTap: widget.onTimestampTap, + onTileTap: widget.onEventTap, + onTileLongTap: widget.onEventLongTap, + onDateLongPress: widget.onDateLongPress, + onDateTap: widget.onDateTap, + onTileDoubleTap: widget.onEventDoubleTap, + eventTileBuilder: _eventTileBuilder, + heightPerMinute: widget.heightPerMinute, + hourIndicatorSettings: _hourIndicatorSettings, + hourLinePainter: _hourLinePainter, + halfHourIndicatorSettings: _halfHourIndicatorSettings, + quarterHourIndicatorSettings: + _quarterHourIndicatorSettings, + dividerSettings: _dividerSettings, + dates: dates, + showLiveLine: widget.showLiveTimeLineInAllDays || + _showLiveTimeIndicator(dates), + timeLineOffset: widget.timeLineOffset, + timeLineWidth: _timeLineWidth, + verticalLineOffset: 0, + showVerticalLine: widget.showVerticalLines, + controller: controller, + hourHeight: _hourHeight, + multiDayViewScrollController: _scrollController, + eventArranger: _eventArranger, + showMutliDayBottomLine: widget.showWeekDayBottomLine, + weekDays: _weekDays, + minuteSlotSize: widget.minuteSlotSize, + scrollConfiguration: _scrollConfiguration, + fullDayEventBuilder: _fullDayEventBuilder, + startHour: _startHour, + showHalfHours: widget.showHalfHours, + showQuarterHours: widget.showQuarterHours, + emulateVerticalOffsetBy: + widget.emulateVerticalOffsetBy, + showWeekDayAtBottom: widget.showWeekDayAtBottom, + endHour: _endHour, + fullDayHeaderTitle: _fullDayHeaderTitle, + fullDayHeaderTextConfig: _fullDayHeaderTextConfig, + lastScrollOffset: _lastScrollOffset, + scrollPhysics: widget.scrollPhysics, + scrollListener: _scrollPageListener, + keepScrollOffset: widget.keepScrollOffset, + backgroundColor: widget.backgroundColor, + ), + ); + }, ), ), ), @@ -639,13 +632,6 @@ class MultiDayViewState extends State> { void _setWeekDays() { _weekDays = WeekDays.values.toSet().toList(); - - // if (!widget.showWeekends) { - // _weekDays - // ..remove(WeekDays.saturday) - // ..remove(WeekDays.sunday); - // } - assert( _weekDays.isNotEmpty, "weekDays can not be empty.\n" @@ -813,16 +799,12 @@ class MultiDayViewState extends State> { Text( widget.weekDayStringBuilder?.call(date.weekday - 1) ?? PackageStrings.currentLocale.weekdays[date.weekday - 1], - style: TextStyle( - color: textColor, - ), + style: TextStyle(color: textColor), ), Text( widget.weekDayDateStringBuilder?.call(date.day) ?? PackageStrings.localizeNumber(date.day), - style: TextStyle( - color: textColor, - ), + style: TextStyle(color: textColor), ), ], ),