Add dynamic theming support to your flutter apps with no stress
In this post, I show you a really simple three-step process for implementing dynamic theming or a light/dark mode switch in your flutter apps with little worry.
Table of contents
1. Adding hive to your project
2. Initialize hive_flutter and open a hive box
3. Listen to theme mode changes
4. Add switch widget to change theme mode
Integrating a light-dark mode option in a Flutter app can be a nightmare. Having to handle providers and shared preferences, as well as loading configurations when the app launches, is quite difficult. But there is good news: in this post, we will learn and explore a straightforward technique to easily create a dynamic theming system for your Flutter app. Let’s get started 🔥
1. Adding hive to your project
To begin, add the hive_flutter package to the flutter project that you want to make theme dynamic.
Hive is a lightweight and blazing fast key-value database written in pure Dart. Inspired by Bitcask.
Add the packages to your flutter project by the following commands
flutter pub add hive_flutter
flutter pub add hive_listener
2. Initialize hive_flutter and open a hive box
To keep the theme mode on the mobile device, we'll use Hive. It is a fast key-value database that makes data persistence in flutter apps simple. It must be initialized before it can be used properly in the app. We will also need a box to house all of our app settings options. Insert this code snippet into your main function in the main.dart file.
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
await Hive.openBox('app_settings');
Hive.box('app_settings').isEmpty
? {
Hive.box('theme').put('theme', false),
}
: null;
runApp(
DynamicThemingApp()
);
}
In the code below, we’ve opened a new box called “app settings” and initialized the hive_flutter package.
It is recommended to verify if the box is empty to avoid null exception problems. In the same way, you can initialize certain keys by assigning default values to them. This is why we added the ternary operator to the code snippet.
In our example, we initialized the “theme” key with the default value false.
This implies that when the app is launched for the first time, the user will not have selected a preferred theme, hence the default theme mode will be light.
3. Listen to theme mode changes
At this point
🥇 hive_flutter package is initialized
🥈 the app settings box is opened
🥉key theme is initialized with the default value of false.
Now we must listen to the box app settings. Here is listening in real time to see if a box’s key has been modified with a new value; this is where the Hive listener package comes in. It monitors box changes and updates the app accordingly. Simply wrap your MaterialApp widget in the HiveListener widget, as seen in this code sample.
class DynamicThemeApp extends StatelessWidget {
const DynamicThemeApp({super.key});
@override
Widget build(BuildContext context) {
return HiveListener(
box: Hive.box('app_settings'),
builder: (box) => MaterialApp(
color: Palette.primary,
themeMode: box.get('theme') ? ThemeMode.dark : ThemeMode.light,
darkTheme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: Palette.backgroundDark,
),
theme: ThemeData(
useMaterial3: true,
primaryColor: Palette.primary,
scaffoldBackgroundColor: Palette.lightGrey,
),
),
);
}
}
4. Add switch widget to change theme mode
Everything is already in place for your app to be theme-dynamic.
Oops! One more thing…..
We need a widget that triggers the theme mode change. In this scenario, using a Switch widget, wrapped with a ValueListenableBuilder that listens to app_settings box might be the best solution. This widget just causes the app settings box to update the value of the theme key based on whether the switch is active or inactive. Because the HiveListener widget that wraps the MaterialApp widget monitors the “app_settings” box modifications, updating the state of the switch widget will cause the theme value to be updated, affecting the app’s theme mode.
ListTile(
leading: const Icon(
Icons.light_mode,
),
trailing: ValueListenableBuilder(
valueListenable:
Hive.box('app_settings').listenable(),
builder: (context, box, widget) =>
CupertinoSwitch(
value: box.get('theme'),
onChanged: (value) {
box.put('theme', value);
},
),
),
subtitle: const Text("Change theme"),
title: const Text("Dark Mode"),
),
You should have a dynamic themed app if you followed all of the instructions for each phase. It’s just like this.
Congratulations 🎉🎉🎉 You have successfully added dynamic mode support to your app in a few simple steps with little worry.
Let’s connect and grow together 🤓
Baimam Boukar JJ
Flutter mobile developer | Open source Evangelist | Cloud & ML enthusiast