Skip to content
Open
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
1 change: 1 addition & 0 deletions example/lib/pages/calendar_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class _CalendarPageState extends State<CalendarPage> {
onDayClicked: _showDayEventsInModalSheet,
minDate: DateTime.now().subtract(const Duration(days: 1000)),
maxDate: DateTime.now().add(const Duration(days: 180)),
//localizedWeekDaysBuilder: (weekDay) => LocalizedWeekDaysWidget(weekDay: weekDay),
),
),
],
Expand Down
35 changes: 35 additions & 0 deletions example/lib/widgets/localized_week_days_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:cr_calendar/cr_calendar.dart';
import 'package:cr_calendar_example/res/colors.dart';
import 'package:flutter/material.dart';

/// Widget that represents week days in row above calendar month view.
class LocalizedWeekDaysWidget extends StatelessWidget {
const LocalizedWeekDaysWidget({
required this.weekDay,
super.key,
});

/// [String] value from [LocalizedWeekDaysBuilder].
final String weekDay;

@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.transparent,
width: 0.3,
),
),
height: 40,
child: Center(
child: Text(
weekDay,
style: TextStyle(
color: violet.withOpacity(0.9),
),
),
),
);
}
}
2 changes: 2 additions & 0 deletions lib/src/contract.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ class Contract {
static const kYearsInLine = 3;

static const kDefaultInitialPage = 4000;

static const kDefaultDayItemBorderWidth = 0.5;
}
33 changes: 31 additions & 2 deletions lib/src/cr_calendar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import 'package:cr_calendar/src/extensions/datetime_ext.dart';
import 'package:cr_calendar/src/models/calendar_event_model.dart';
import 'package:cr_calendar/src/month_item.dart';
import 'package:cr_calendar/src/utils/debouncer.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:jiffy/jiffy.dart';

Expand Down Expand Up @@ -217,6 +216,7 @@ class CrCalendar extends StatefulWidget {
this.onSwipeCallbackDebounceMs = 100,
this.minDate,
this.maxDate,
this.localizedWeekDaysBuilder,
super.key,
}) : assert(maxEventLines <= 6, 'maxEventLines should be less then 6'),
assert(minDate == null || maxDate == null || minDate.isBefore(maxDate),
Expand Down Expand Up @@ -279,6 +279,21 @@ class CrCalendar extends StatefulWidget {
/// Reduces number of callbacks when [CrCalendarController] goToDate is used.
final int onSwipeCallbackDebounceMs;

/// Builder function for week day customization at the top of the calendar.
///
/// When this parameter is not null, it will be called with each week days first
/// letter as a String, eg. S for Sunday, M for Monday, etc.
///
/// When this parameter is not null, the first day of the week is determined
/// by the app's current locale, which is en_US in Flutter by default.
///
/// The week day names will be translated for the current locale as well,
/// eg. if the current locale is German, then M for Montag, D for Dienstag etc.
///
/// When this parameter is not null, [firstDayOfWeek] and [weekDaysBuilder]
/// parameters are ignored.
final LocalizedWeekDaysBuilder? localizedWeekDaysBuilder;

@override
_CrCalendarState createState() => _CrCalendarState();
}
Expand All @@ -290,6 +305,8 @@ class _CrCalendarState extends State<CrCalendar> {

final _minPage = 1;

late WeekDay _firstWeekDay;

@override
void initState() {
super.initState();
Expand All @@ -311,6 +328,7 @@ class _CrCalendarState extends State<CrCalendar> {

@override
Widget build(BuildContext context) {
_initializeFirstDayOfWeek();
return OrientationBuilder(
builder: (BuildContext context, Orientation orientation) {
return PageView.builder(
Expand Down Expand Up @@ -354,7 +372,8 @@ class _CrCalendarState extends State<CrCalendar> {
},
weekDaysBuilder: widget.weekDaysBuilder,
dayItemBuilder: widget.dayItemBuilder,
firstWeekDay: widget.firstDayOfWeek,
firstWeekDay: _firstWeekDay,
localizedWeekDaysBuilder: widget.localizedWeekDaysBuilder,
),
);
},
Expand Down Expand Up @@ -439,4 +458,14 @@ class _CrCalendarState extends State<CrCalendar> {
widget.controller.page;
}
}

void _initializeFirstDayOfWeek() {
final localizations = MaterialLocalizations.of(context);

if (widget.localizedWeekDaysBuilder != null) {
_firstWeekDay = WeekDay.values[localizations.firstDayOfWeekIndex];
} else {
_firstWeekDay = widget.firstDayOfWeek;
}
}
}
5 changes: 5 additions & 0 deletions lib/src/customization/builders.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ typedef PickerButtonBuilder = Widget? Function(Function? onPress);
/// Callback for getting date range data from [CrDatePickerDialog].
typedef OnDateRangeSelected = void Function(
DateTime? rangeBegin, DateTime? rangeEnd);

/// Builder for week day customization at the top of the calendar widget.
/// The weekdays first letter in uppercase is passed as a String,
/// eg. M (Monday), T (Tuesday) etc.
typedef LocalizedWeekDaysBuilder = Widget Function(String weekDay);
47 changes: 39 additions & 8 deletions lib/src/month_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:cr_calendar/src/models/event_count_keeper.dart';
import 'package:cr_calendar/src/month_calendar_widget.dart';
import 'package:cr_calendar/src/utils/event_utils.dart';
import 'package:cr_calendar/src/widgets/default_weekday_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:jiffy/jiffy.dart';

Expand All @@ -29,6 +28,7 @@ class MonthItem extends StatefulWidget {
this.eventTopPadding = 0,
this.onDayTap,
this.firstWeekDay = WeekDay.sunday,
this.localizedWeekDaysBuilder,
super.key,
});

Expand All @@ -46,6 +46,7 @@ class MonthItem extends StatefulWidget {
final double? eventTopPadding;
final TouchMode touchMode;
final WeekDay firstWeekDay;
final LocalizedWeekDaysBuilder? localizedWeekDaysBuilder;

@override
MonthItemState createState() => MonthItemState();
Expand Down Expand Up @@ -114,9 +115,13 @@ class MonthItemState extends State<MonthItem> {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: _getDaysOfWeek(),
LayoutBuilder(
builder: (context, constraint) {
final size = _getConstrainedSize(constraint);
return Row(
children: _getDaysOfWeek(size.width),
);
},
),
Expanded(
child: LayoutBuilder(
Expand Down Expand Up @@ -212,15 +217,41 @@ class MonthItemState extends State<MonthItem> {
}

/// Returns list of week days representation
List<Widget> _getDaysOfWeek() {
List<Widget> _getDaysOfWeek(double itemWidth) {
if (widget.localizedWeekDaysBuilder != null) {
return _getLocalizedDaysOfWeek(itemWidth);
}
final sortedWeekDays = sortWeekdays(widget.firstWeekDay);
final week = List<Widget>.generate(WeekDay.values.length, (index) {
final sortedWeekDays = sortWeekdays(widget.firstWeekDay);
return widget.weekDaysBuilder?.call(sortedWeekDays[index]) ??
DefaultWeekdayWidget(day: sortedWeekDays[index]);
return Container(
width: itemWidth,
child: widget.weekDaysBuilder?.call(sortedWeekDays[index]) ??
DefaultWeekdayWidget(day: sortedWeekDays[index]),
);
});
return week;
}

List<Widget> _getLocalizedDaysOfWeek(double itemWidth) {
final localizations = MaterialLocalizations.of(context);
final result = <Widget>[];

var i = localizations.firstDayOfWeekIndex;
while (true) {
final weekday = localizations.narrowWeekdays[i];
result.add(Container(
width: itemWidth,
child: widget.localizedWeekDaysBuilder!.call(weekday),
));
if (i == (localizations.firstDayOfWeekIndex - 1) % 7) {
break;
}
i = (i + 1) % 7;
}

return result;
}

/// Returns list of events for current month
List<WeekDrawer> _calculateWeeks() {
final begin = _beginRange;
Expand Down
6 changes: 5 additions & 1 deletion lib/src/widgets/day_item.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cr_calendar/src/contract.dart';
import 'package:flutter/material.dart';

///Represent calendar day body
Expand Down Expand Up @@ -27,7 +28,10 @@ class DayItem extends StatelessWidget {
Container(
alignment: Alignment.topCenter,
decoration: BoxDecoration(
border: Border.all(width: 0.5, color: Colors.black12),
border: Border.all(
width: Contract.kDefaultDayItemBorderWidth,
color: Colors.black12,
),
color: isSelectedDay || isWithinRange ? Colors.black12 : null,
),
child: Column(
Expand Down
6 changes: 6 additions & 0 deletions lib/src/widgets/default_weekday_widget.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cr_calendar/src/contract.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

Expand All @@ -14,6 +15,11 @@ class DefaultWeekdayWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
width: Contract.kDefaultDayItemBorderWidth,
color: Colors.transparent),
),
height: 40,
child: Center(
child: Text(
Expand Down