Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Fixes issue #385: Add showWeekends flag in month view #422

Merged
merged 1 commit into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -199,4 +204,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
5 changes: 4 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,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(
Expand Down
1 change: 1 addition & 0 deletions example/lib/widgets/week_view_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class WeekViewWidget extends StatelessWidget {
return WeekView(
key: state,
width: width,
showWeekends: false,
showLiveTimeLineInAllDays: true,
eventArranger: SideEventArranger(maxWidth: 30),
timeLineWidth: 65,
Expand Down
56 changes: 42 additions & 14 deletions lib/src/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<DateTime> datesOfWeek({WeekDays start = WeekDays.monday}) {
List<DateTime> 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
Expand All @@ -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
Expand All @@ -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<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 = true,
}) {
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).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;
}
Expand Down
117 changes: 71 additions & 46 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,10 @@ 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 +180,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 @@ -342,7 +339,10 @@ class MonthViewState<T extends Object?> extends State<MonthView<T>> {
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,
Expand All @@ -352,7 +352,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 @@ -364,36 +364,45 @@ class MonthViewState<T extends Object?> extends State<MonthView<T>> {
),
),
Expanded(
child: LayoutBuilder(builder: (context, constraints) {
final _cellAspectRatio =
widget.useAvailableVerticalSpace
? calculateCellAspectRatio(
constraints.maxHeight,
)
: widget.cellAspectRatio;

return SizedBox(
height: _height,
width: _width,
child: _MonthPageBuilder<T>(
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<T>(
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,
),
);
},
),
),
],
);
Expand Down Expand Up @@ -432,8 +441,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 +676,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 +694,36 @@ 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 = 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)
? <CalendarEventData<T>>[]
: controller.getEventsOnDay(monthDays[index]);
return GestureDetector(
onTap: () => onCellTap?.call(events, monthDays[index]),
onLongPress: () => onDateLongPress?.call(monthDays[index]),
Expand Down
5 changes: 4 additions & 1 deletion lib/src/week_view/week_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,10 @@ class WeekViewState<T extends Object?> extends State<WeekView<T>> {
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,
Expand Down
Loading