MD Sarfaraj
Posted on July 16, 2022
Without further ado, let's get started with today's article where I'll talk about how to implement dark mode in an app and manage Flutter state using the provider package.
What is state management in Flutter?
State management refers to managing the states of UI controls based on business logic requirements, as most often one or more controls are dependent upon each other.
Note: To change the state of a widget in Flutter, we use the setState method.
Examples
Let's say you have a ToDo app, and you have added an item to your list. You must refresh the page in order to see the item. In this situation, state management kicks in, allowing you to add, edit, and delete ToDo items without needing to reload the page.
You can learn more about Flutter state management by visiting the following link.
What is the provider package?
The provider package is created by Remi Rousselet to handle the state as cleanly as possible. Widgets in Provider update as soon as they become aware of changes in the state.
Example
Let's say you have an app and you want to add dark mode features to it, but when you enable dark mode, it should change the color scheme of the whole app, not just a single page. Since setState does not reflect changes in the entire app, we need a provider package at this point.
Let's understand some methods before using the provider package:
ChangeNotifierProvider: This is the app's entry point to enable the provider package.
Provider.of<>(): Interacts between data holder(ChangeNotifier) and Consumer.
Consumer: Uses data from ChangeNotifier.
ChangeNotifier: The ChangeNotifier class holds data.
notifierListener: This method is equivalent to setState.
For more information you can check out this link.
Implement the dark mode in the Flutter app
First, you must include these two packages in your pubspec.yaml file.
provider: ^6.0.2
shared_preferences: ^2.0.13
Do the pub get after adding these two dependencies to pubspec.yaml.
Create these files under your lib folder,
themes/theme_color_scheme.dart
import 'package:flutter/material.dart';
class ThemeColor {
static ThemeData themeData(bool isDarkMode, BuildContext context) {
return ThemeData(
primarySwatch: Colors.blue,
primaryColor: isDarkMode ? Colors.black : Colors.white,
backgroundColor: isDarkMode ? Colors.black : Color(0xFFF1F5FB),
indicatorColor: isDarkMode ? Color(0xFF0E1D36) : Color(0xFFCBDCF8),
buttonColor: isDarkMode ? Color(0xFF3B3B3B) : Color(0xff133762),
hintColor: isDarkMode ? Color(0xFF280C0B) : Color(0xff133762),
highlightColor: isDarkMode ? Color(0xFF372901) : Color(0xff133762),
hoverColor: isDarkMode ? Color(0xFF3A3A3B) : Color(0xff133762),
focusColor: isDarkMode ? Color(0xFF0B2512) : Color(0xff133762),
disabledColor: Colors.grey,
textSelectionColor: isDarkMode ? Colors.white : Colors.black,
cardColor: isDarkMode ? Color(0xFF151515) : Colors.white,
canvasColor: isDarkMode ? Colors.black : Colors.grey[50],
brightness: isDarkMode ? Brightness.dark : Brightness.light,
buttonTheme: Theme.of(context).buttonTheme.copyWith(
colorScheme: isDarkMode ? ColorScheme.dark() : ColorScheme.light()),
appBarTheme: AppBarTheme(
elevation: 0,
),
);
}
}
themes/theme_preference.dart
import 'package:shared_preferences/shared_preferences.dart';
class ThemePreference {
static const theme_status = "THEMESTATUS";
setDarkTheme(bool value) async {
SharedPreferences preferences = await SharedPreferences.getInstance();
preferences.setBool(theme_status, value);
}
Future<bool> getTheme() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
return preferences.getBool(theme_status) ?? false;
}
}
themes/theme_provider.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter_dark_mode/themes/theme_preference.dart';
class ThemeProvider with ChangeNotifier {
ThemePreference themePreference = ThemePreference();
bool _darkTheme = false;
bool get darkTheme => _darkTheme;
set darkTheme(bool value) {
_darkTheme = value;
themePreference.setDarkTheme(value);
notifyListeners();
}
}
screens/home_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_dark_mode/themes/theme_provider.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
final themeChange = Provider.of<ThemeProvider>(context);
void toggleSwitch(bool value) {
if (themeChange.darkTheme == false) {
setState(() {
themeChange.darkTheme = true;
});
} else {
setState(() {
themeChange.darkTheme = false;
});
}
}
return Scaffold(
appBar: AppBar(
title: Text("Dark Theme Demo"),
),
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
child: Column(
children: [
Container(
padding: const EdgeInsets.only(bottom: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Dark theme",
style: TextStyle(fontSize: 18),
),
Switch(
onChanged: toggleSwitch,
value: themeChange.darkTheme,
),
],
),
),
const Divider(),
],
),
),
),
);
}
}
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_dark_mode/screens/home_screen.dart';
import 'package:flutter_dark_mode/themes/theme_color_scheme.dart';
import 'package:flutter_dark_mode/themes/theme_provider.dart';
import 'package:provider/provider.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ThemeProvider themeChangeProvider = ThemeProvider();
@override
void initState() {
super.initState();
getCurrentAppTheme();
}
void getCurrentAppTheme() async {
themeChangeProvider.darkTheme =
await themeChangeProvider.themePreference.getTheme();
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) {
return themeChangeProvider;
},
child: Consumer<ThemeProvider>(
builder: (BuildContext context, value, child) {
return MaterialApp(
title: 'Dark Theme',
debugShowCheckedModeBanner: false,
theme: ThemeColor.themeData(themeChangeProvider.darkTheme, context),
home: HomeScreen(),
);
},
),
);
}
}
Everything is done. Run your app now.
You can download the source code from the GitHub repository.
Conclusion
This article shows you how to use the provider package to manage the Flutter app state and create dark mode features in your app. Please feel free to share, like, and comment if you enjoyed this article.
The article is sponsored by: UniqueApps
Posted on July 16, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.