Welcome Flutter developers! We will talk about a very hot trend in user interface design - "dark mode". As businesses cater to user-centric designs, more and more apps are implementing dark mode for better user experience and reduced digital eye strain. Flutter, being a versatile framework, offers an efficient way to implement a switch between light and dark themes in your Flutter apps.
In the Flutter universe, everything revolves around widgets. A Flutter theme is just another widget that wraps the MaterialApp to set the colors for your application. A theme in Flutter is a class that provides colors for your application's UI. We’ll begin implementing dark mode in Flutter by understanding the basic theme structure.
A Flutter theme is, in essence, an instance of the Theme Data class that provides colors for your app's widgets. Widgets use these colors to decide how to render themselves — in a light theme, dark theme, or any custom theme you might devise.
1class MyApp extends StatelessWidget { 2 @override 3 Widget build(BuildContext context) { 4 return MaterialApp( 5 theme: ThemeData.light(), 6 darkTheme: ThemeData.dark(), 7 home: MyHomePage(), 8 ); 9 } 10}
Here, ThemeData.light() and ThemeData.dark() are the default themes provided by Flutter. One signifies light mode, the other dark mode. ThemeData encapsulates the color schemes and allows us to implement the dark theme in our Flutter app.
The MaterialApp widget then takes both themes and uses them based on the system theme. Amazing, right? However, what if you want a custom theme or switch between light and dark modes within the app?
We will explore the step-by-step process and illustrate the code snippets for achieving this. Here we go.
Setting up your Flutter application for implementing the dark theme is simple. Firstly, you have to create a new Flutter project.
1 flutter create flutter_dark_mode 2 cd flutter_dark_mode
This will create a new Flutter project.
Implementing a Flutter dark mode in an app involves creating a mechanism to switch between the dark and light themes, depending on user preference or system settings. Let’s see how this can be achieved.
Firstly, define the colors you want to use for your both light and dark themes.
1class MyAppColors { 2 static final darkBlue = Color(0xFF1E1E2C); 3 static final lightBlue = Color(0xFF2D2D44); 4}
These colors will be used for creating ThemeData later.
Create two ThemeData instances for the light and the dark theme, and use colors from the previous step.
1class MyAppThemes { 2 static final lightTheme = ThemeData( 3 primaryColor: MyAppColors.lightBlue, 4 brightness: Brightness.light, 5 ); 6 7 static final darkTheme = ThemeData( 8 primaryColor: MyAppColors.darkBlue, 9 brightness: Brightness.dark, 10 ); 11}
Now, it's time to utilize these themes in the MaterialApp widget. We can set the theme property to the light theme and darkTheme property to the dark theme.
1class MyApp extends StatelessWidget { 2 @override 3 Widget build(BuildContext context) { 4 return MaterialApp( 5 title: 'Flutter Dark Mode', 6 theme: MyAppThemes.lightTheme, 7 darkTheme: MyAppThemes.darkTheme, 8 themeMode: ThemeMode.system, // Default mode 9 home: const MyHomePage(title: 'Flutter Dark Mode'), 10 ); 11 } 12}
In this example, ThemeMode.system will automatically apply the light or dark theme based on system settings.
To dynamically switch between light and dark themes, you can add a switch on the AppBar in MyHomePage widget. Depending upon the current theme mode, the switch will render, and upon toggling, it will call toggleTheme method. This method will change the state of _themeMode which will rebuild our app with new theme.
1class MyHomePage extends StatefulWidget { 2 MyHomePage({Key key, this.title}) : super(key: key); 3 final String title; 4 5 @override 6 _MyHomePageState createState() => _MyHomePageState(); 7} 8 9class _MyHomePageState extends State<MyHomePage> { 10 ThemeMode _themeMode = ThemeMode.system; 11 12 void _toggleTheme(ThemeMode themeMode) { 13 setState(() { 14 _themeMode = themeMode; 15 }); 16 } 17 18 @override 19 Widget build(BuildContext context) { 20 bool isDarkMode = Theme.of(context).brightness == Brightness.dark; 21 22 return Scaffold( 23 appBar: AppBar( 24 title: Text(widget.title), 25 actions: <Widget>[ 26 Switch( 27 value: isDarkMode, 28 onChanged: (isOn) { 29 isOn 30 ? _toggleTheme(ThemeMode.dark) 31 : _toggleTheme(ThemeMode.light); 32 }, 33 ), 34 ], 35 ), 36 ); 37 } 38}
Now, we have a switch on the AppBar, allowing the user to toggle between light and dark modes. But this change will not persist if the app restarts. For that, we need to use Flutter plugins to persist theme changes.
For the final step, we will test the App for the changes we have implemented for the Light and Dark modes.
1void main() { 2 runApp(MyApp()); 3}
After running your app, test the theme change functionality. You should be able to see light and dark modes being applied throughout your app, and you can confirm this by toggling the switch in the AppBar.
Keep in mind that as of now, the switch doesn't app-wide persist the chosen theme. To maintain the state of the chosen theme after the app restarts, you will need to use persisted state management libraries.
Adding a dark mode to Flutter apps is straightforward, however, there are few things you must take care of to avoid common pitfalls and ensure a smoother development and user experience.
To automatically apply light or dark theme based on system settings, set the themeMode to ThemeMode.system. If you want to assign a manual control to the user to select light or dark theme, it's better to use a dynamic toggle as we've seen earlier.
1MaterialApp( 2 themeMode: ThemeMode.system, // Automatically apply light or dark theme as per system settings. 3);
When applying themes, be sure to define dark mode properties for each widget, if you're using custom widgets or particularly stylized ones. Not every widget in Flutter will automatically adapt to the app's theme.
While this is more design knowledge than Flutter specific, it’s important to keep contrast and readability in mind when choosing colors for your dark mode. Text should stand out clearly against its background. The Material Design Guide to Dark Theme provides guidelines for choosing colors with an emphasis on contrast and readability in the dark mode.
One of the common challenges you may face is to persist the user's chosen theme upon app restarts. Currently, the Flutter framework does not provide an out-of-the-box solution for this. For persisting the user's choice, you can use a package like shared_preferences.
Lastly, don't forget to test your application’s dark mode on multiple devices, particularly with different operating systems. The behavior of system-wide dark mode can sometimes behave unexpectedly, particularly in older OS versions.
Now that you have a good handle on implementing dark mode and light mode, as well as some potential issues to watch for, you can provide this feature in your Flutter apps with a lot less headache.
Isn't it fascinating how, with just a few tweaks, you can improve the experience of your Flutter app users by providing them with the flexibility of a dark mode? Not only does this feature cater to differing user preferences, but it also has potential benefits in reducing eye strain.
Although Flutter provides default themes, it's powerful (and fun!) to create your custom themes for light and dark modes. Always remember, while implementing such features, be mindful of the design guidelines, maintain the state of the chosen theme, and test it across multiple devices.
Indeed, adding a dark mode is just a user interface feature, but it sends a clear message to your users that you care about their needs and comfort.
Happy coding, and remember, the world becomes 'dark mode friendly' one Flutter app at a time.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.