diff --git a/example/lib/main.dart b/example/lib/main.dart index 146e23af..4735cb2a 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -43,7 +43,7 @@ List _events = [ endTime: DateTime(_now.year, _now.month, _now.day, 22), ), CalendarEventData( - date: _now.add(Duration(days: 1)), + date: _now.add(Duration(days: 2)), startTime: DateTime(_now.year, _now.month, _now.day, 18), endTime: DateTime(_now.year, _now.month, _now.day, 19), title: "Wedding anniversary", diff --git a/example/lib/widgets/month_view_widget.dart b/example/lib/widgets/month_view_widget.dart index bacec7eb..4eade8a3 100644 --- a/example/lib/widgets/month_view_widget.dart +++ b/example/lib/widgets/month_view_widget.dart @@ -18,6 +18,8 @@ class MonthViewWidget extends StatelessWidget { return MonthView( key: state, width: width, + showWeekends: false, + useAvailableVerticalSpace: true, hideDaysNotInMonth: false, onEventTap: (event, date) { Navigator.of(context).push( diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index 36077fd0..29f937fe 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -87,9 +87,32 @@ 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}) { + List datesOfMonths({ + WeekDays startDay = WeekDays.monday, + bool hideDaysNotInMonth = false, + bool showWeekends = false, + }) { final monthDays = []; + // Start is the first weekday for each week in a month for (var i = 1, start = 1; i < 7; i++, start += 7) { + // Any date of week is in current month + final anyDateInCurrentMonth = + DateTime(year, month, start).datesOfWeek(start: startDay).any((date) { + if (showWeekends) { + // Include all days + return date.month == month; + } else { + // Exclude weekends (Saturday and Sunday) + return (date.weekday != DateTime.saturday && + date.weekday != DateTime.sunday) && + date.month == month; + } + }); + + // if entire row contains dates of next month then skip it + if (hideDaysNotInMonth && !anyDateInCurrentMonth) { + continue; + } monthDays .addAll(DateTime(year, month, start).datesOfWeek(start: startDay)); } diff --git a/lib/src/month_view/month_view.dart b/lib/src/month_view/month_view.dart index 51690910..65475ef4 100644 --- a/lib/src/month_view/month_view.dart +++ b/lib/src/month_view/month_view.dart @@ -64,6 +64,11 @@ 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 +189,7 @@ class MonthView extends StatefulWidget { this.maxMonth, this.controller, this.initialMonth, + this.showWeekends = true, this.borderSize = 1, this.useAvailableVerticalSpace = false, this.cellAspectRatio = 0.55, @@ -352,7 +358,7 @@ class MonthViewState extends State> { width: _width, child: Row( children: List.generate( - 7, + widget.showWeekends ? 7 : 5, (index) => Expanded( child: SizedBox( width: _cellWidth, @@ -365,10 +371,15 @@ class MonthViewState extends State> { ), Expanded( child: LayoutBuilder(builder: (context, constraints) { + final dates = date.datesOfMonths( + startDay: widget.startDay, + hideDaysNotInMonth: widget.hideDaysNotInMonth, + ); final _cellAspectRatio = widget.useAvailableVerticalSpace ? calculateCellAspectRatio( - constraints.maxHeight, + height: constraints.maxHeight, + daysInMonth: dates.length, ) : widget.cellAspectRatio; @@ -391,6 +402,7 @@ class MonthViewState extends State> { startDay: widget.startDay, physics: widget.pagePhysics, hideDaysNotInMonth: widget.hideDaysNotInMonth, + weekDays: widget.showWeekends ? 7 : 5, ), ); }), @@ -432,8 +444,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 +679,7 @@ class _MonthPageBuilder extends StatelessWidget { final WeekDays startDay; final ScrollPhysics physics; final bool hideDaysNotInMonth; + final int weekDays; const _MonthPageBuilder({ Key? key, @@ -680,25 +697,32 @@ 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 = _filteredDays; + + // 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]), @@ -724,6 +748,22 @@ class _MonthPageBuilder extends StatelessWidget { ), ); } + + List get _filteredDays { + final monthDays = date.datesOfMonths( + startDay: startDay, + hideDaysNotInMonth: hideDaysNotInMonth, + ); + + return monthDays.where((day) { + final isWeekend = + day.weekday == DateTime.saturday || day.weekday == DateTime.sunday; + if (weekDays == 5 && isWeekend) { + return false; + } + return true; + }).toList(); + } } class MonthHeader {