Skip to content
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
website. [#469](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/pull/469)
- Fixed resizing the window automatically scrolls the page to the top in
example app. [#480](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/480)
- Adds support for dark theme. [#263](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/263)

# [1.4.0 - 7 Jan 2025](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/tree/1.4.0)

Expand Down
129 changes: 129 additions & 0 deletions doc/theme_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
## **Customise theme**
The default theme supports dark mode. Refer this colors to override it.

| Name | Parameter | Default color |
|-----------------------------------------------|------------------------|-------------------------------------|
| `MonthView` Border color | Color? borderColor | colorScheme.surfaceContainerHigh |
| `WeekView` Background color of week view page | Color? backgroundColor | colorScheme.surfaceContainerLowest |
| `DayView` Default background color | Color? backgroundColor | colorScheme.surfaceContainerLow |
| `FilledCell` Dates in month cell color | Color? backgroundColor | colorScheme.surfaceContainerLowest |
| `FilledCell` Dates not in month cell color | Color? backgroundColor | colorScheme.surfaceContainerLow |
| `WeekDayTile` Border color | Color? borderColor | colorScheme.secondaryContainer |
| `WeekDayTile` Background color | Color? backgroundColor | colorScheme.surfaceContainerHigh |
| `WeekDayTile` Text style color | TextStyle? textStyle | colorScheme.onSecondaryContainer |

To customise `MonthView`, `DayView` & `WeekView` page header use `HeaderStyle`.

```dart
headerStyle: HeaderStyle(
leftIconConfig: IconDataConfig(color: Colors.red),
rightIconConfig: IconDataConfig(color: Colors.red),
decoration: BoxDecoration(
color: Theme.of(context).highlightColor,
),
),
```

### Theme implementation approaches

There are two main ways to customize the theme for calendar views:

1. **Using ThemeData extensions**:
```dart
// Create custom theme
final myMonthViewTheme = MonthViewTheme.light().copyWith(
cellInMonthColor: Colors.blue.shade50,
cellBorderColor: Colors.blue.shade300,
);

// Apply to your app theme
final theme = ThemeData.light().copyWith(
extensions: [
myMonthViewTheme,
DayViewTheme.light(),
WeekViewTheme.light(),
],
);
```

2. **Using CalendarThemeProvider**:
```dart
CalendarThemeProvider(
calendarTheme: CalendarTheme(
monthViewTheme: MonthViewTheme.light().copyWith(
cellInMonthColor: Colors.blue.shade50,
),
dayViewTheme: DayViewTheme.light(),
weekViewTheme: WeekViewTheme.light(),
),
child: YourApp(),
)
```

### Day view
* Default timeline text color is `colorScheme.onSurface`.
* Use `markingStyle` in `DefaultTimeLineMark` to give text style.
* Default `LiveTimeIndicatorSettings` color `colorScheme.primaryColorLight`.
* Use `liveTimeIndicatorSettings` to customise it.
* Default hour, half hour & quarter color is `colorScheme.surfaceContainerHighest`.
* Use `hourIndicatorSettings` to customise it.

Default hour indicator settings.
```dart
HourIndicatorSettings(
height: widget.heightPerMinute,
// Color of horizontal and vertical lines
color: Theme.of(context).colorScheme.surfaceContainerHighest,
offset: 5,
);
```

### Week view
* To customise week number & weekdays use `weekNumberBuilder` & `weekDayBuilder`.
* Default week tile background color is `colorScheme.surfaceContainerHigh`.
* Use `weekTitleBackgroundColor` to change background color.
* Default page background color is `colorScheme.surfaceContainerLowest`.
* Use `backgroundColor` to change background color.
* Default timeline text color is `colorScheme.onSurface`. Use `markingStyle` in `DefaultTimeLineMark` to give text style.
* To customise timeline use `timeLineBuilder`.
* To change Hour lines color use `HourIndicatorSettings`.
* To style hours, half hours & quarter hours use `HourIndicatorSettings`. Default color used is `surfaceContainerHighest`

```dart
hourIndicatorSettings: HourIndicatorSettings(
color: Colors.greenAccent,
lineStyle: LineStyle.dashed,
),
showHalfHours: true,
halfHourIndicatorSettings: HourIndicatorSettings(
color: Colors.redAccent,
lineStyle: LineStyle.dashed,
),
```

### Month view

* Default date cell color in month is `colorScheme.surfaceContainerLowest` and `colorScheme.surfaceContainerLow` for days not in month.
* Use `cellBuilder` to completely customize the cell appearance:

```dart
cellBuilder: (date, events, isToday, isInMonth, hideDaysNotInMonth) {
return Container(
decoration: BoxDecoration(
color: isInMonth ? Colors.white : Colors.grey[200],
border: Border.all(color: Colors.blue),
),
child: Center(
child: Text(
date.day.toString(),
style: TextStyle(
color: isToday ? Colors.red : Colors.black,
fontWeight: isToday ? FontWeight.bold : FontWeight.normal,
),
),
),
);
}
```
* Use `showWeekTileBorder` to control week day title border visibility
* Use `headerBuilder` to customize or completely replace the month header
4 changes: 2 additions & 2 deletions example/lib/constants.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';

import 'app_colors.dart';
import 'theme/app_colors.dart';

class AppConstants {
AppConstants._();
Expand All @@ -11,7 +11,7 @@ class AppConstants {
borderRadius: BorderRadius.circular(7),
borderSide: BorderSide(
width: 2,
color: AppColors.lightNavyBlue,
color: AppColors.outlineVariant,
),
);

Expand Down
9 changes: 8 additions & 1 deletion example/lib/extension.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

import 'app_colors.dart';
import 'enumerations.dart';
import 'theme/app_colors.dart';
import 'theme/app_theme_extension.dart';

enum TimeStampFormat { parse_12, parse_24 }

Expand Down Expand Up @@ -128,3 +129,9 @@ extension StringExt on String {
extension ViewNameExt on CalendarView {
String get name => toString().split(".").last;
}

extension BuildContextExtension on BuildContext {
AppThemeExtension get appColors =>
Theme.of(this).extension<AppThemeExtension>() ??
AppThemeExtension.light();
}
56 changes: 42 additions & 14 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,34 +1,62 @@
import 'dart:ui';

import 'package:calendar_view/calendar_view.dart';
import 'package:example/theme/app_theme.dart';
import 'package:flutter/material.dart';

import 'pages/home_page.dart';
import 'theme/app_colors.dart';

DateTime get _now => DateTime.now();

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
bool isDarkMode = false;

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return CalendarControllerProvider(
controller: EventController()..addAll(_events),
child: MaterialApp(
title: 'Flutter Calendar Page Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData.light(),
scrollBehavior: ScrollBehavior().copyWith(
dragDevices: {
PointerDeviceKind.trackpad,
PointerDeviceKind.mouse,
PointerDeviceKind.touch,
},
return CalendarThemeProvider(
calendarTheme: CalendarThemeData(
monthViewTheme:
isDarkMode ? MonthViewThemeData.dark() : MonthViewThemeData.light(),
dayViewTheme: isDarkMode
? DayViewThemeData.dark()
: DayViewThemeData.light()
.copyWith(hourLineColor: AppColors.primary) as DayViewThemeData,
weekViewTheme:
isDarkMode ? WeekViewThemeData.dark() : WeekViewThemeData.light(),
multiDayViewTheme: isDarkMode
? MultiDayViewThemeData.dark()
: MultiDayViewThemeData.light(),
),
child: CalendarControllerProvider(
controller: EventController()..addAll(_events),
child: MaterialApp(
title: 'Flutter Calendar Page Demo',
debugShowCheckedModeBanner: false,
theme: AppTheme.light,
darkTheme: AppTheme.dark,
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
scrollBehavior: ScrollBehavior().copyWith(
dragDevices: {
PointerDeviceKind.trackpad,
PointerDeviceKind.mouse,
PointerDeviceKind.touch,
},
),
home: HomePage(
onChangeTheme: (isDark) => setState(() => isDarkMode = isDark),
),
),
home: HomePage(),
),
);
}
Expand Down
8 changes: 4 additions & 4 deletions example/lib/pages/create_event_page.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:calendar_view/calendar_view.dart';
import 'package:flutter/material.dart';

import '../app_colors.dart';
import '../extension.dart';
import '../widgets/add_event_form.dart';

Expand All @@ -12,22 +11,23 @@ class CreateEventPage extends StatelessWidget {

@override
Widget build(BuildContext context) {
final themeColor = context.appColors;

return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
centerTitle: false,
leading: IconButton(
onPressed: context.pop,
icon: Icon(
Icons.arrow_back,
color: AppColors.black,
color: themeColor.onPrimary,
),
),
title: Text(
event == null ? "Create New Event" : "Update Event",
style: TextStyle(
color: AppColors.black,
color: themeColor.onPrimary,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
Expand Down
11 changes: 10 additions & 1 deletion example/lib/pages/day_view_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@ class DayViewPageDemo extends StatefulWidget {
class _DayViewPageDemoState extends State<DayViewPageDemo> {
@override
Widget build(BuildContext context) {
final appColors = context.appColors;

return ResponsiveWidget(
webWidget: WebHomePage(
selectedView: CalendarView.day,
),
mobileWidget: Scaffold(
primary: false,
appBar: AppBar(
leading: const SizedBox.shrink(),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
child: Icon(
Icons.add,
color: appColors.onPrimary,
),
elevation: 8,
onPressed: () => context.pushRoute(CreateEventPage()),
),
Expand Down
21 changes: 19 additions & 2 deletions example/lib/pages/event_details_page.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:calendar_view/calendar_view.dart';
import 'package:example/theme/app_colors.dart';
import 'package:example/widgets/delete_event_dialog.dart';
import 'package:flutter/material.dart';

Expand Down Expand Up @@ -97,16 +98,30 @@ class DetailsPage extends StatelessWidget {
children: [
Expanded(
child: ElevatedButton(
child: Text(
'Delete Event',
style: TextStyle(
color: AppColors.black,
),
),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white70,
),
onPressed: () async {
await _handleDeleteEvent(context);
Navigator.of(context).pop();
},
child: Text('Delete Event'),
),
),
SizedBox(width: 30),
Expanded(
child: ElevatedButton(
child: Text(
'Edit Event',
style: TextStyle(
color: AppColors.black,
),
),
onPressed: () async {
final result = await Navigator.of(context).push(
MaterialPageRoute(
Expand All @@ -120,7 +135,9 @@ class DetailsPage extends StatelessWidget {
Navigator.of(context).pop();
}
},
child: Text('Edit Event'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white70,
),
),
),
],
Expand Down
13 changes: 10 additions & 3 deletions example/lib/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ import 'mobile/mobile_home_page.dart';
import 'web/web_home_page.dart';

class HomePage extends StatelessWidget {
const HomePage({super.key});
const HomePage({
this.onChangeTheme,
super.key,
});

/// Return true for dark mode
/// false for light mode
final void Function(bool)? onChangeTheme;

@override
Widget build(BuildContext context) {
return ResponsiveWidget(
mobileWidget: MobileHomePage(),
webWidget: WebHomePage(),
mobileWidget: MobileHomePage(onChangeTheme: onChangeTheme),
webWidget: WebHomePage(onThemeChange: onChangeTheme),
);
}
}
Loading