diff --git a/CHANGELOG.md b/CHANGELOG.md index 34481d87..40e28339 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# [1.4.0](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/tree/1.4.0) +- Adds `showWeekends` flag in month view to hide & show weekends view. + Default is `showWeekends = true` shows all weekdays. [#385](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/385) +- Events are now hidden for days not in the current month when hideDaysNotInMonth = true + # [1.3.0 - 12 Nov 2024](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/tree/1.3.0) - Fixes full day event position when fullHeaderTitle is empty. @@ -199,4 +204,4 @@ # [0.0.1 - 26 Aug 2021](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/tree/0.0.1) -- Initial release \ No newline at end of file +- Initial release diff --git a/README.md b/README.md index 1476d0d2..55732861 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,7 @@ MonthView( headerBuilder: MonthHeader.hidden, // To hide month header showWeekTileBorder: false, // To show or hide header border hideDaysNotInMonth: true, // To hide days or cell that are not in current month + showWeekends: false, // To hide weekends default value is true ); ``` diff --git a/example/lib/widgets/month_view_widget.dart b/example/lib/widgets/month_view_widget.dart index bacec7eb..b3d2a7f4 100644 --- a/example/lib/widgets/month_view_widget.dart +++ b/example/lib/widgets/month_view_widget.dart @@ -18,7 +18,10 @@ class MonthViewWidget extends StatelessWidget { return MonthView( key: state, width: width, - hideDaysNotInMonth: false, + showWeekends: false, + startDay: WeekDays.friday, + useAvailableVerticalSpace: true, + hideDaysNotInMonth: true, onEventTap: (event, date) { Navigator.of(context).push( MaterialPageRoute( diff --git a/example/lib/widgets/week_view_widget.dart b/example/lib/widgets/week_view_widget.dart index 765e8fcb..af2dd30f 100644 --- a/example/lib/widgets/week_view_widget.dart +++ b/example/lib/widgets/week_view_widget.dart @@ -14,6 +14,7 @@ class WeekViewWidget extends StatelessWidget { return WeekView( key: state, width: width, + showWeekends: false, showLiveTimeLineInAllDays: true, eventArranger: SideEventArranger(maxWidth: 30), timeLineWidth: 65, diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index 36077fd0..6a07c690 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -52,7 +52,10 @@ extension DateTimeExtensions on DateTime { /// will return dates /// [6,7,8,9,10,11,12] /// Where on 6th there will be monday and on 12th there will be Sunday - List datesOfWeek({WeekDays start = WeekDays.monday}) { + List datesOfWeek({ + WeekDays start = WeekDays.monday, + bool showWeekEnds = true, + }) { // Here %7 ensure that we do not subtract >6 and <0 days. // Initial formula is, // difference = (weekday - startInt)%7 @@ -63,16 +66,19 @@ extension DateTimeExtensions on DateTime { // final startDay = DateTime(year, month, day - (weekday - start.index - 1) % 7); - - return [ - startDay, - DateTime(startDay.year, startDay.month, startDay.day + 1), - DateTime(startDay.year, startDay.month, startDay.day + 2), - DateTime(startDay.year, startDay.month, startDay.day + 3), - DateTime(startDay.year, startDay.month, startDay.day + 4), - DateTime(startDay.year, startDay.month, startDay.day + 5), - DateTime(startDay.year, startDay.month, startDay.day + 6), - ]; + // Generate weekdays with weekends or without weekends + final days = List.generate( + 7, + (index) => DateTime(startDay.year, startDay.month, startDay.day + index), + ) + .where( + (date) => + showWeekEnds || + (date.weekday != DateTime.saturday && + date.weekday != DateTime.sunday), + ) + .toList(); + return days; } /// Returns the first date of week containing the current date @@ -87,11 +93,33 @@ extension DateTimeExtensions on DateTime { /// All the dates are week based that means it will return array of size 42 /// which will contain 6 weeks that is the maximum number of weeks a month /// can have. - List datesOfMonths({WeekDays startDay = WeekDays.monday}) { + /// + /// It excludes week if `hideDaysNotInMonth` is set true and + /// if all dates in week comes in next month then it will excludes that week. + List datesOfMonths({ + WeekDays startDay = WeekDays.monday, + bool hideDaysNotInMonth = false, + bool showWeekends = true, + }) { final monthDays = []; + // Start is the first weekday for each week in a month for (var i = 1, start = 1; i < 7; i++, start += 7) { - monthDays - .addAll(DateTime(year, month, start).datesOfWeek(start: startDay)); + final datesInWeek = + DateTime(year, month, start).datesOfWeek(start: startDay).where( + (day) => + showWeekends || + (day.weekday != DateTime.saturday && + day.weekday != DateTime.sunday), + ); + // Check does every date of week belongs to different month + final allDatesNotInCurrentMonth = datesInWeek.every((date) { + return date.month != month; + }); + // if entire row contains dates of other month then skip it + if (hideDaysNotInMonth && allDatesNotInCurrentMonth) { + continue; + } + monthDays.addAll(datesInWeek); } return monthDays; } diff --git a/lib/src/month_view/month_view.dart b/lib/src/month_view/month_view.dart index 51690910..b4fbc428 100644 --- a/lib/src/month_view/month_view.dart +++ b/lib/src/month_view/month_view.dart @@ -4,16 +4,8 @@ import 'package:flutter/material.dart'; -import '../calendar_constants.dart'; -import '../calendar_controller_provider.dart'; -import '../calendar_event_data.dart'; -import '../components/components.dart'; +import '../../calendar_view.dart'; import '../constants.dart'; -import '../enumerations.dart'; -import '../event_controller.dart'; -import '../extensions.dart'; -import '../style/header_style.dart'; -import '../typedefs.dart'; class MonthView extends StatefulWidget { /// A function that returns a [Widget] that determines appearance of @@ -64,6 +56,10 @@ class MonthView extends StatefulWidget { /// This method will be called when user double taps on event tile. final TileTapCallback? onEventDoubleTap; + /// Show weekends or not. + /// Default value is true. + final bool showWeekends; + /// Builds the name of the weeks. /// /// Used default week builder if null. @@ -184,6 +180,7 @@ class MonthView extends StatefulWidget { this.maxMonth, this.controller, this.initialMonth, + this.showWeekends = true, this.borderSize = 1, this.useAvailableVerticalSpace = false, this.cellAspectRatio = 0.55, @@ -342,7 +339,10 @@ class MonthViewState extends State> { onPageChanged: _onPageChange, itemBuilder: (_, index) { final date = DateTime(_minDate.year, _minDate.month + index); - final weekDays = date.datesOfWeek(start: widget.startDay); + final weekDays = date.datesOfWeek( + start: widget.startDay, + showWeekEnds: widget.showWeekends, + ); return Column( mainAxisSize: MainAxisSize.min, @@ -352,7 +352,7 @@ class MonthViewState extends State> { width: _width, child: Row( children: List.generate( - 7, + widget.showWeekends ? 7 : 5, (index) => Expanded( child: SizedBox( width: _cellWidth, @@ -364,36 +364,45 @@ class MonthViewState extends State> { ), ), Expanded( - child: LayoutBuilder(builder: (context, constraints) { - final _cellAspectRatio = - widget.useAvailableVerticalSpace - ? calculateCellAspectRatio( - constraints.maxHeight, - ) - : widget.cellAspectRatio; - - return SizedBox( - height: _height, - width: _width, - child: _MonthPageBuilder( - key: ValueKey(date.toIso8601String()), - onCellTap: widget.onCellTap, - onDateLongPress: widget.onDateLongPress, - width: _width, - height: _height, - controller: controller, - borderColor: widget.borderColor, - borderSize: widget.borderSize, - cellBuilder: _cellBuilder, - cellRatio: _cellAspectRatio, - date: date, - showBorder: widget.showBorder, + child: LayoutBuilder( + builder: (context, constraints) { + final dates = date.datesOfMonths( startDay: widget.startDay, - physics: widget.pagePhysics, hideDaysNotInMonth: widget.hideDaysNotInMonth, - ), - ); - }), + showWeekends: widget.showWeekends, + ); + final _cellAspectRatio = + widget.useAvailableVerticalSpace + ? calculateCellAspectRatio( + height: constraints.maxHeight, + daysInMonth: dates.length, + ) + : widget.cellAspectRatio; + + return SizedBox( + height: _height, + width: _width, + child: _MonthPageBuilder( + key: ValueKey(date.toIso8601String()), + onCellTap: widget.onCellTap, + onDateLongPress: widget.onDateLongPress, + width: _width, + height: _height, + controller: controller, + borderColor: widget.borderColor, + borderSize: widget.borderSize, + cellBuilder: _cellBuilder, + cellRatio: _cellAspectRatio, + date: date, + showBorder: widget.showBorder, + startDay: widget.startDay, + physics: widget.pagePhysics, + hideDaysNotInMonth: widget.hideDaysNotInMonth, + weekDays: widget.showWeekends ? 7 : 5, + ), + ); + }, + ), ), ], ); @@ -432,8 +441,12 @@ class MonthViewState extends State> { _height = _cellHeight * 6; } - double calculateCellAspectRatio(double height) { - final _cellHeight = height / 6; + double calculateCellAspectRatio({ + required double height, + required int daysInMonth, + }) { + final rows = daysInMonth / 7; + final _cellHeight = height / rows; return _cellWidth / _cellHeight; } @@ -663,6 +676,7 @@ class _MonthPageBuilder extends StatelessWidget { final WeekDays startDay; final ScrollPhysics physics; final bool hideDaysNotInMonth; + final int weekDays; const _MonthPageBuilder({ Key? key, @@ -680,25 +694,36 @@ class _MonthPageBuilder extends StatelessWidget { required this.startDay, required this.physics, required this.hideDaysNotInMonth, + required this.weekDays, }) : super(key: key); @override Widget build(BuildContext context) { - final monthDays = date.datesOfMonths(startDay: startDay); - return Container( + final monthDays = date.datesOfMonths( + startDay: startDay, + hideDaysNotInMonth: hideDaysNotInMonth, + showWeekends: weekDays == 7, + ); + + // Highlight tiles which is not in current month + return SizedBox( width: width, height: height, child: GridView.builder( padding: EdgeInsets.zero, physics: physics, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 7, + crossAxisCount: weekDays, childAspectRatio: cellRatio, ), - itemCount: 42, + itemCount: monthDays.length, shrinkWrap: true, itemBuilder: (context, index) { - final events = controller.getEventsOnDay(monthDays[index]); + // Hide events if `hideDaysNotInMonth` true + final events = + hideDaysNotInMonth & (monthDays[index].month != date.month) + ? >[] + : controller.getEventsOnDay(monthDays[index]); return GestureDetector( onTap: () => onCellTap?.call(events, monthDays[index]), onLongPress: () => onDateLongPress?.call(monthDays[index]), diff --git a/lib/src/week_view/week_view.dart b/lib/src/week_view/week_view.dart index f5fd9cbc..2b074370 100644 --- a/lib/src/week_view/week_view.dart +++ b/lib/src/week_view/week_view.dart @@ -514,7 +514,10 @@ class WeekViewState extends State> { itemBuilder: (_, index) { final dates = DateTime(_minDate.year, _minDate.month, _minDate.day + (index * DateTime.daysPerWeek)) - .datesOfWeek(start: widget.startDay); + .datesOfWeek( + start: widget.startDay, + showWeekEnds: widget.showWeekends, + ); return ValueListenableBuilder( valueListenable: _scrollConfiguration,