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 16, 2024
1 parent cc99a0e commit e98b9e7
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 23 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# [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)
- Fixes issue: Event is shown when days not in current month is hidden `hideDaysNotInMonth = true`.
Events are now hidden for days not in the current month if `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.
Expand Down Expand Up @@ -199,4 +205,4 @@

# [0.0.1 - 26 Aug 2021](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/tree/0.0.1)

- Initial release
- Initial release
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
```

Expand Down
4 changes: 3 additions & 1 deletion example/lib/widgets/month_view_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ class MonthViewWidget extends StatelessWidget {
return MonthView(
key: state,
width: width,
hideDaysNotInMonth: false,
showWeekends: false,
useAvailableVerticalSpace: true,
hideDaysNotInMonth: true,
onEventTap: (event, date) {
Navigator.of(context).push(
MaterialPageRoute(
Expand Down
32 changes: 29 additions & 3 deletions lib/src/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,37 @@ 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}) {
///
/// 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<DateTime> datesOfMonths({
WeekDays startDay = WeekDays.monday,
bool hideDaysNotInMonth = false,
bool showWeekends = false,
}) {
final monthDays = <DateTime>[];
// 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);
// Check does every date of week belongs to different month
final allDatesNotInCurrentMonth = datesInWeek.every((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 other month then skip it
if (hideDaysNotInMonth && allDatesNotInCurrentMonth) {
continue;
}
monthDays.addAll(datesInWeek);
}
return monthDays;
}
Expand Down
82 changes: 64 additions & 18 deletions lib/src/month_view/month_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<T extends Object?> extends StatefulWidget {
/// A function that returns a [Widget] that determines appearance of
Expand Down Expand Up @@ -64,6 +56,14 @@ 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.
///
/// Similar to [WeekView],
/// If it is false week view will remove weekends from week days
/// and events on weekends will not be shown.
final bool showWeekends;

/// Builds the name of the weeks.
///
/// Used default week builder if null.
Expand Down Expand Up @@ -184,6 +184,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 +353,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,10 +366,16 @@ class MonthViewState<T extends Object?> extends State<MonthView<T>> {
),
Expanded(
child: LayoutBuilder(builder: (context, constraints) {
final dates = date.datesOfMonths(
startDay: widget.startDay,
hideDaysNotInMonth: widget.hideDaysNotInMonth,
showWeekends: widget.showWeekends,
);
final _cellAspectRatio =
widget.useAvailableVerticalSpace
? calculateCellAspectRatio(
constraints.maxHeight,
height: constraints.maxHeight,
daysInMonth: dates.length,
)
: widget.cellAspectRatio;

Expand All @@ -391,6 +398,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 +440,12 @@ 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 int daysInMonth,
}) {
final rows = daysInMonth / 7;
final _cellHeight = height / rows;
return _cellWidth / _cellHeight;
}

Expand Down Expand Up @@ -663,6 +675,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,25 +693,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(
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)
? <CalendarEventData<T>>[]
: controller.getEventsOnDay(monthDays[index]);
return GestureDetector(
onTap: () => onCellTap?.call(events, monthDays[index]),
onLongPress: () => onDateLongPress?.call(monthDays[index]),
Expand All @@ -724,6 +744,32 @@ class _MonthPageBuilder<T> extends StatelessWidget {
),
);
}

/// Returns a list of dates for the month, excluding weekends
/// if the weekDays parameter is set or showWeekends = false.
///
/// This getter first retrieves all the dates of the month using the
/// `datesOfMonths` method, considering the `startDay` and
/// `hideDaysNotInMonth` parameters.
/// It then filters out the weekend dates (Saturday and Sunday)
/// if the `weekDays` parameter is set to 5, ensuring only
/// weekdays are included in the returned list.
List<DateTime> get _filteredDays {
final monthDays = date.datesOfMonths(
startDay: startDay,
hideDaysNotInMonth: hideDaysNotInMonth,
showWeekends: weekDays == 7,
);

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 {
Expand Down

0 comments on commit e98b9e7

Please sign in to comment.