Skip to content

Commit 8e41a94

Browse files
feat: Fixes issue #263: ✨ Support for dark theme
1 parent 469cc29 commit 8e41a94

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1222
-225
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# [1.4.1 - Unreleased]
22

33
- Adds clear method to `EventController`.
4+
- Adds support for dark theme. [#263](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/263)
45

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

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,46 @@ WeekView(
355355

356356
Above code will create `WeekView` with only five days, from monday to friday.
357357

358+
## **Customise theme**
359+
* The default theme includes support for dark mode.
360+
* For detailed instructions on how to override the default colors please refer to [this](doc/theme_guide.md) guide.
361+
362+
### Day view
363+
* Default timeline text color is `colorScheme.onSurface`.
364+
* Default hour, half hour & quarter color is `colorScheme.surfaceContainerHighest`.
365+
* Default timeline color `colorScheme.primaryColorLight`.
366+
367+
Default hour indicator settings.
368+
```dart
369+
HourIndicatorSettings(
370+
height: widget.heightPerMinute,
371+
// Color of horizontal and vertical lines
372+
color: Theme.of(context).colorScheme.surfaceContainerHighest,
373+
offset: 5,
374+
);
375+
```
376+
377+
### Week view
378+
* Week-number text color - Default color `onSecondaryContainer`.
379+
* To customise week number & weekdays use `weekNumberBuilder` & `weekDayBuilder`.
380+
* Default week tile color is `colorScheme.surfaceContainerHigh`.
381+
* To give background color use `backgroundColor` Default background color is `colorScheme.surfaceContainerLowest`.
382+
* To customise timeline use `timeLineBuilder`. Default text color is `colorScheme.onSurface`.
383+
* To change Hour lines color use `HourIndicatorSettings`.
384+
* To style hours, half hours & quarter hours use `HourIndicatorSettings`. Default color used is `surfaceContainerHighest`
385+
386+
```dart
387+
hourIndicatorSettings: HourIndicatorSettings(
388+
color: Colors.greenAccent,
389+
lineStyle: LineStyle.dashed,
390+
),
391+
showHalfHours: true,
392+
halfHourIndicatorSettings: HourIndicatorSettings(
393+
color: Colors.redAccent,
394+
lineStyle: LineStyle.dashed,
395+
),
396+
```
397+
358398
## Main Contributors
359399

360400
<table>

doc/theme_guide.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
## **Customise theme**
2+
The default theme supports dark mode. Refer this colors to override it.
3+
4+
| Name | Parameter | Default color |
5+
|-----------------------------------------------|------------------------|-------------------------------------|
6+
| `MonthView` Border color | Color? borderColor | colorScheme.surfaceContainerHigh |
7+
| `WeekView` Background color of week view page | Color? backgroundColor | colorScheme.surfaceContainerLowest |
8+
| `DayView` Default background color | Color? backgroundColor | colorScheme.surfaceContainerLow |
9+
| `FilledCell` Dates in month cell color | Color? backgroundColor | colorScheme.surfaceContainerLowest |
10+
| `FilledCell` Dates not in month cell color | Color? backgroundColor | colorScheme.surfaceContainerLow |
11+
| `WeekDayTile` Border color | Color? borderColor | colorScheme.secondaryContainer |
12+
| `WeekDayTile` Background color | Color? backgroundColor | colorScheme.surfaceContainerHigh |
13+
| `WeekDayTile` Text style color | TextStyle? textStyle | colorScheme.onSecondaryContainer |
14+
15+
To customise `MonthView`, `DayView` & `WeekView` page header use `HeaderStyle`.
16+
17+
```dart
18+
headerStyle: HeaderStyle(
19+
leftIconConfig: IconDataConfig(color: Colors.red),
20+
rightIconConfig: IconDataConfig(color: Colors.red),
21+
decoration: BoxDecoration(
22+
color: Theme.of(context).highlightColor,
23+
),
24+
),
25+
```
26+
27+
### Day view
28+
* Default timeline text color is `colorScheme.onSurface`.
29+
* Use `markingStyle` in `DefaultTimeLineMark` to give text style.
30+
* Default `LiveTimeIndicatorSettings` color `colorScheme.primaryColorLight`.
31+
* Use `liveTimeIndicatorSettings` to customise it.
32+
* Default hour, half hour & quarter color is `colorScheme.surfaceContainerHighest`.
33+
* Use `hourIndicatorSettings` to customise it.
34+
35+
Default hour indicator settings.
36+
```dart
37+
HourIndicatorSettings(
38+
height: widget.heightPerMinute,
39+
// Color of horizontal and vertical lines
40+
color: Theme.of(context).colorScheme.surfaceContainerHighest,
41+
offset: 5,
42+
);
43+
```
44+
45+
### Week view
46+
* To customise week number & weekdays use `weekNumberBuilder` & `weekDayBuilder`.
47+
* Default week tile background color is `colorScheme.surfaceContainerHigh`.
48+
* Use `weekTitleBackgroundColor` to change background color.
49+
* Default page background color is `colorScheme.surfaceContainerLowest`.
50+
* Use `backgroundColor` to change background color.
51+
* Default timeline text color is `colorScheme.onSurface`. Use `markingStyle` in `DefaultTimeLineMark` to give text style.
52+
* To customise timeline use `timeLineBuilder`.
53+
* To change Hour lines color use `HourIndicatorSettings`.
54+
* To style hours, half hours & quarter hours use `HourIndicatorSettings`. Default color used is `surfaceContainerHighest`
55+
56+
```dart
57+
hourIndicatorSettings: HourIndicatorSettings(
58+
color: Colors.greenAccent,
59+
lineStyle: LineStyle.dashed,
60+
),
61+
showHalfHours: true,
62+
halfHourIndicatorSettings: HourIndicatorSettings(
63+
color: Colors.redAccent,
64+
lineStyle: LineStyle.dashed,
65+
),
66+
```

example/lib/constants.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:flutter/material.dart';
22

3-
import 'app_colors.dart';
3+
import 'theme/app_colors.dart';
44

55
class AppConstants {
66
AppConstants._();
@@ -11,7 +11,7 @@ class AppConstants {
1111
borderRadius: BorderRadius.circular(7),
1212
borderSide: BorderSide(
1313
width: 2,
14-
color: AppColors.lightNavyBlue,
14+
color: AppColors.outlineVariant,
1515
),
1616
);
1717

example/lib/extension.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
import 'package:example/theme/app_theme_extension.dart';
12
import 'package:flutter/material.dart';
23
import 'package:intl/intl.dart';
34

4-
import 'app_colors.dart';
55
import 'enumerations.dart';
6+
import 'theme/app_colors.dart';
67

78
enum TimeStampFormat { parse_12, parse_24 }
89

@@ -128,3 +129,9 @@ extension StringExt on String {
128129
extension ViewNameExt on CalendarView {
129130
String get name => toString().split(".").last;
130131
}
132+
133+
extension BuildContextExtension on BuildContext {
134+
AppThemeExtension get appColors =>
135+
Theme.of(this).extension<AppThemeExtension>() ??
136+
AppThemeExtension.light();
137+
}

example/lib/main.dart

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:ui';
22

33
import 'package:calendar_view/calendar_view.dart';
4+
import 'package:example/theme/app_theme.dart';
45
import 'package:flutter/material.dart';
56

67
import 'pages/home_page.dart';
@@ -11,7 +12,14 @@ void main() {
1112
runApp(MyApp());
1213
}
1314

14-
class MyApp extends StatelessWidget {
15+
class MyApp extends StatefulWidget {
16+
@override
17+
State<MyApp> createState() => _MyAppState();
18+
}
19+
20+
class _MyAppState extends State<MyApp> {
21+
bool isDarkMode = false;
22+
1523
// This widget is the root of your application.
1624
@override
1725
Widget build(BuildContext context) {
@@ -20,15 +28,19 @@ class MyApp extends StatelessWidget {
2028
child: MaterialApp(
2129
title: 'Flutter Calendar Page Demo',
2230
debugShowCheckedModeBanner: false,
23-
theme: ThemeData.light(),
31+
theme: AppTheme.light,
32+
darkTheme: AppTheme.dark,
33+
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
2434
scrollBehavior: ScrollBehavior().copyWith(
2535
dragDevices: {
2636
PointerDeviceKind.trackpad,
2737
PointerDeviceKind.mouse,
2838
PointerDeviceKind.touch,
2939
},
3040
),
31-
home: HomePage(),
41+
home: HomePage(
42+
onChangeTheme: (isDark) => setState(() => isDarkMode = isDark),
43+
),
3244
),
3345
);
3446
}

example/lib/pages/create_event_page.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'package:calendar_view/calendar_view.dart';
22
import 'package:flutter/material.dart';
33

4-
import '../app_colors.dart';
54
import '../extension.dart';
65
import '../widgets/add_event_form.dart';
76

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

1312
@override
1413
Widget build(BuildContext context) {
14+
final themeColor = context.appColors;
15+
1516
return Scaffold(
1617
appBar: AppBar(
1718
elevation: 0,
18-
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
1919
centerTitle: false,
2020
leading: IconButton(
2121
onPressed: context.pop,
2222
icon: Icon(
2323
Icons.arrow_back,
24-
color: AppColors.black,
24+
color: themeColor.onPrimary,
2525
),
2626
),
2727
title: Text(
2828
event == null ? "Create New Event" : "Update Event",
2929
style: TextStyle(
30-
color: AppColors.black,
30+
color: themeColor.onPrimary,
3131
fontSize: 20.0,
3232
fontWeight: FontWeight.bold,
3333
),

example/lib/pages/day_view_page.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,22 @@ class DayViewPageDemo extends StatefulWidget {
1717
class _DayViewPageDemoState extends State<DayViewPageDemo> {
1818
@override
1919
Widget build(BuildContext context) {
20+
final appColors = context.appColors;
21+
2022
return ResponsiveWidget(
2123
webWidget: WebHomePage(
2224
selectedView: CalendarView.day,
2325
),
2426
mobileWidget: Scaffold(
27+
primary: false,
28+
appBar: AppBar(
29+
leading: const SizedBox.shrink(),
30+
),
2531
floatingActionButton: FloatingActionButton(
26-
child: Icon(Icons.add),
32+
child: Icon(
33+
Icons.add,
34+
color: appColors.onPrimary,
35+
),
2736
elevation: 8,
2837
onPressed: () => context.pushRoute(CreateEventPage()),
2938
),

example/lib/pages/event_details_page.dart

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:calendar_view/calendar_view.dart';
2+
import 'package:example/theme/app_colors.dart';
23
import 'package:example/widgets/delete_event_dialog.dart';
34
import 'package:flutter/material.dart';
45

@@ -97,16 +98,30 @@ class DetailsPage extends StatelessWidget {
9798
children: [
9899
Expanded(
99100
child: ElevatedButton(
101+
child: Text(
102+
'Delete Event',
103+
style: TextStyle(
104+
color: AppColors.black,
105+
),
106+
),
107+
style: ElevatedButton.styleFrom(
108+
backgroundColor: Colors.white70,
109+
),
100110
onPressed: () async {
101111
await _handleDeleteEvent(context);
102112
Navigator.of(context).pop();
103113
},
104-
child: Text('Delete Event'),
105114
),
106115
),
107116
SizedBox(width: 30),
108117
Expanded(
109118
child: ElevatedButton(
119+
child: Text(
120+
'Edit Event',
121+
style: TextStyle(
122+
color: AppColors.black,
123+
),
124+
),
110125
onPressed: () async {
111126
final result = await Navigator.of(context).push(
112127
MaterialPageRoute(
@@ -120,7 +135,9 @@ class DetailsPage extends StatelessWidget {
120135
Navigator.of(context).pop();
121136
}
122137
},
123-
child: Text('Edit Event'),
138+
style: ElevatedButton.styleFrom(
139+
backgroundColor: Colors.white70,
140+
),
124141
),
125142
),
126143
],

example/lib/pages/home_page.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@ import 'mobile/mobile_home_page.dart';
55
import 'web/web_home_page.dart';
66

77
class HomePage extends StatelessWidget {
8-
const HomePage({super.key});
8+
const HomePage({
9+
this.onChangeTheme,
10+
super.key,
11+
});
12+
13+
/// Return true for dark mode
14+
/// false for light mode
15+
final void Function(bool)? onChangeTheme;
916

1017
@override
1118
Widget build(BuildContext context) {
1219
return ResponsiveWidget(
13-
mobileWidget: MobileHomePage(),
14-
webWidget: WebHomePage(),
20+
mobileWidget: MobileHomePage(onChangeTheme: onChangeTheme),
21+
webWidget: WebHomePage(onThemeChange: onChangeTheme),
1522
);
1623
}
1724
}

example/lib/pages/mobile/mobile_home_page.dart

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,21 @@ import '../day_view_page.dart';
55
import '../month_view_page.dart';
66
import '../week_view_page.dart';
77

8-
class MobileHomePage extends StatelessWidget {
8+
class MobileHomePage extends StatefulWidget {
9+
MobileHomePage({
10+
this.onChangeTheme,
11+
super.key,
12+
});
13+
14+
final void Function(bool)? onChangeTheme;
15+
16+
@override
17+
State<MobileHomePage> createState() => _MobileHomePageState();
18+
}
19+
20+
class _MobileHomePageState extends State<MobileHomePage> {
21+
bool isDarkMode = false;
22+
923
@override
1024
Widget build(BuildContext context) {
1125
return Scaffold(
@@ -38,6 +52,19 @@ class MobileHomePage extends StatelessWidget {
3852
],
3953
),
4054
),
55+
floatingActionButton: FloatingActionButton(
56+
child: Icon(
57+
Icons.dark_mode,
58+
color: context.appColors.onPrimary,
59+
),
60+
onPressed: () {
61+
isDarkMode = !isDarkMode;
62+
if (widget.onChangeTheme != null) {
63+
widget.onChangeTheme!(isDarkMode);
64+
}
65+
setState(() {});
66+
},
67+
),
4168
);
4269
}
4370
}

0 commit comments

Comments
 (0)