Skip to content

Commit

Permalink
feat: Fixes issue #385: Add showWeekends flag in month view
Browse files Browse the repository at this point in the history
  • Loading branch information
shubham-jitiya-simform committed Dec 3, 2024
1 parent cc99a0e commit 533ac77
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 29 deletions.
2 changes: 1 addition & 1 deletion example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
Expand Down
2 changes: 1 addition & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ List<CalendarEventData> _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",
Expand Down
2 changes: 2 additions & 0 deletions example/lib/widgets/month_view_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
21 changes: 20 additions & 1 deletion lib/src/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,28 @@ 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<DateTime> datesOfMonths({WeekDays startDay = WeekDays.monday}) {
List<DateTime> datesOfMonths({
WeekDays startDay = WeekDays.monday,
bool hideDaysNotInMonth = false,
}) {
final monthDays = <DateTime>[];
// Start is the first weekday for each week in a month
// If showWeekends is false, max rows we need to generate is 5.
final lastDateOfFirstWeek = firstDayOfWeek().add(Duration(days: 4));
for (var i = 1, start = 1; i < 7; i++, start += 7) {
// Update last date: Friday's date
// No any date is in current month
final anyDateInCurrentMonth = DateTime(year, month, start)
.datesOfWeek(start: startDay)
.any((date) => date.month == month);
if (hideDaysNotInMonth &&
start == 1 &&
lastDateOfFirstWeek.month != month) {
continue;
}
if (hideDaysNotInMonth && i == 6 && !anyDateInCurrentMonth) {
continue;
}
monthDays
.addAll(DateTime(year, month, start).datesOfWeek(start: startDay));
}
Expand Down
131 changes: 105 additions & 26 deletions lib/src/month_view/month_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ class MonthView<T extends Object?> extends StatefulWidget {
/// This method will be called when user double taps on event tile.
final TileTapCallback<T>? onEventDoubleTap;

/// Show weekends or not
///
/// Default value is true.
final bool showWeekends;

/// Builds the name of the weeks.
///
/// Used default week builder if null.
Expand Down Expand Up @@ -184,6 +189,7 @@ class MonthView<T extends Object?> extends StatefulWidget {
this.maxMonth,
this.controller,
this.initialMonth,
this.showWeekends = true,
this.borderSize = 1,
this.useAvailableVerticalSpace = false,
this.cellAspectRatio = 0.55,
Expand Down Expand Up @@ -352,7 +358,7 @@ class MonthViewState<T extends Object?> extends State<MonthView<T>> {
width: _width,
child: Row(
children: List.generate(
7,
widget.showWeekends ? 7 : 5,
(index) => Expanded(
child: SizedBox(
width: _cellWidth,
Expand All @@ -365,12 +371,15 @@ class MonthViewState<T extends Object?> extends State<MonthView<T>> {
),
Expanded(
child: LayoutBuilder(builder: (context, constraints) {
final _cellAspectRatio =
widget.useAvailableVerticalSpace
? calculateCellAspectRatio(
constraints.maxHeight,
)
: widget.cellAspectRatio;
final _cellAspectRatio = widget
.useAvailableVerticalSpace
? calculateCellAspectRatio(
height: constraints.maxHeight,
date: date,
startDay: widget.startDay,
hideDaysNotInMonth: widget.hideDaysNotInMonth,
)
: widget.cellAspectRatio;

return SizedBox(
height: _height,
Expand All @@ -391,6 +400,7 @@ class MonthViewState<T extends Object?> extends State<MonthView<T>> {
startDay: widget.startDay,
physics: widget.pagePhysics,
hideDaysNotInMonth: widget.hideDaysNotInMonth,
weekDays: widget.showWeekends ? 7 : 5,
),
);
}),
Expand Down Expand Up @@ -432,8 +442,21 @@ class MonthViewState<T extends Object?> extends State<MonthView<T>> {
_height = _cellHeight * 6;
}

double calculateCellAspectRatio(double height) {
final _cellHeight = height / 6;
double calculateCellAspectRatio({
required double height,
required DateTime date,
required WeekDays startDay,
required hideDaysNotInMonth,
}) {
// Required rows
final daysInMonth = date
.datesOfMonths(
startDay: startDay,
hideDaysNotInMonth: hideDaysNotInMonth,
)
.length /
7;
final _cellHeight = height / daysInMonth;
return _cellWidth / _cellHeight;
}

Expand Down Expand Up @@ -663,6 +686,7 @@ class _MonthPageBuilder<T> extends StatelessWidget {
final WeekDays startDay;
final ScrollPhysics physics;
final bool hideDaysNotInMonth;
final int weekDays;

const _MonthPageBuilder({
Key? key,
Expand All @@ -680,30 +704,32 @@ class _MonthPageBuilder<T> 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(
width: width,
height: height,
child: GridView.builder(
padding: EdgeInsets.zero,
physics: physics,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 7,
childAspectRatio: cellRatio,
),
itemCount: 42,
shrinkWrap: true,
itemBuilder: (context, index) {
final events = controller.getEventsOnDay(monthDays[index]);
return GestureDetector(
// There can we 20 days or 25 days
// Update start day
final monthDays = date.datesOfMonths(
startDay: startDay, hideDaysNotInMonth: hideDaysNotInMonth);
final maxCells = _getMaxCells(monthDays.length);
final gridViewItems = <Widget>[];
for (var index = 0; index < monthDays.length; index++) {
final events = controller.getEventsOnDay(monthDays[index]);
bool isWeekend = monthDays[index].weekday == DateTime.saturday ||
monthDays[index].weekday == DateTime.sunday;
if (isWeekend && weekDays == 5) {
continue;
}
if (!isWeekend || isWeekend && weekDays == 7) {
gridViewItems.add(
GestureDetector(
onTap: () => onCellTap?.call(events, monthDays[index]),
onLongPress: () => onDateLongPress?.call(monthDays[index]),
child: Container(
decoration: BoxDecoration(
color: Colors.transparent,
border: showBorder
? Border.all(
color: borderColor,
Expand All @@ -719,11 +745,64 @@ class _MonthPageBuilder<T> extends StatelessWidget {
hideDaysNotInMonth,
),
),
);
),
);
}
}

// Highlight tiles which is not in current month
return Container(
width: width,
height: height,
child: GridView.builder(
padding: EdgeInsets.zero,
physics: physics,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: weekDays,
childAspectRatio: cellRatio,
),
itemCount: maxCells,
shrinkWrap: true,
itemBuilder: (context, index) {
if (index > gridViewItems.length - 1) {
return Container(
decoration: BoxDecoration(
color: Colors.grey[200],
border: showBorder
? Border.all(
color: borderColor,
width: borderSize,
)
: null,
));
}
return gridViewItems[index];
},
),
);
}

int _getMaxCells(int daysInMonth) {
// Show weekends - true
if (weekDays == 7) {
// Show days not in month
if (!hideDaysNotInMonth) {
return 42;
}
return daysInMonth <= 28 ? 28 : 35;
} else {
// Hide weekends and show days not in month
if (!hideDaysNotInMonth) {
// 6 weeks: 5 week days * 6 weeks = 30
return 30;
} else {
// When weekends are hidden & hide days not in month is true
// If daysInMonth is less than 28 max rows we can have is 4 otherwise 5.
// Weekends are included in daysInMonth
return daysInMonth <= 28 ? 20 : 25;
}
}
}
}

class MonthHeader {
Expand Down

0 comments on commit 533ac77

Please sign in to comment.