I want to create a flutter app that has 2 light and dark mode themes that change by a switch in-app and the default theme is default android theme.
I need to pass some custom color to the fellow widget and I don't want to just config material theme.
Use the system setting (Settings -> Display -> Theme) to enable Dark theme. Use the Quick Settings tile to switch themes from the notification tray (once enabled). On Pixel devices, selecting the Battery Saver mode enables Dark theme at the same time.
In Flutter, we can change the theme throughout the app with the help of ThemeData in MaterialApp constructor. The default theme will be shared throughout the app when no theme is provided. ); ThemeData is used to configure the appearance of the entire app.
Steps to change theme text color in Flutter You can change theme text color in Flutter, by defining the TextTheme (inside MaterialApp) and then adding headings type. For example, headline1 , headline2 , BodyText1 , and so on. After that, you can assign the TextStyle widget with the color of your choice.
Run the flutter packages get in the terminal inside your project and install the package. Now we will add a Switch Widget in the UI to switch between the Themes. Now we need to add a Listener to listen to the changes and update the theme. We have to go to our Top most widget and update the code like this.
The easiest way in my opinion is by using provider to manage the state of your app and shared_preferences to save your theme preference on file system. By following this procedure you can save your theme so the user doesn't have to switch theme every time.
Output
You can easily store your theme preference in form of a string and then at the start of your app check if there is value stored on file system, if so apply that theme as shown below.
StorageManager.dart
import 'package:shared_preferences/shared_preferences.dart'; class StorageManager { static void saveData(String key, dynamic value) async { final prefs = await SharedPreferences.getInstance(); if (value is int) { prefs.setInt(key, value); } else if (value is String) { prefs.setString(key, value); } else if (value is bool) { prefs.setBool(key, value); } else { print("Invalid Type"); } } static Future<dynamic> readData(String key) async { final prefs = await SharedPreferences.getInstance(); dynamic obj = prefs.get(key); return obj; } static Future<bool> deleteData(String key) async { final prefs = await SharedPreferences.getInstance(); return prefs.remove(key); } }
Define your theme properties in a theme variable like below and initialize your _themedata variable on the basis of value inside storage.
ThemeManager.dart
import 'package:flutter/material.dart'; import '../services/storage_manager.dart'; class ThemeNotifier with ChangeNotifier { final darkTheme = ThemeData( primarySwatch: Colors.grey, primaryColor: Colors.black, brightness: Brightness.dark, backgroundColor: const Color(0xFF212121), accentColor: Colors.white, accentIconTheme: IconThemeData(color: Colors.black), dividerColor: Colors.black12, ); final lightTheme = ThemeData( primarySwatch: Colors.grey, primaryColor: Colors.white, brightness: Brightness.light, backgroundColor: const Color(0xFFE5E5E5), accentColor: Colors.black, accentIconTheme: IconThemeData(color: Colors.white), dividerColor: Colors.white54, ); ThemeData _themeData; ThemeData getTheme() => _themeData; ThemeNotifier() { StorageManager.readData('themeMode').then((value) { print('value read from storage: ' + value.toString()); var themeMode = value ?? 'light'; if (themeMode == 'light') { _themeData = lightTheme; } else { print('setting dark theme'); _themeData = darkTheme; } notifyListeners(); }); } void setDarkMode() async { _themeData = darkTheme; StorageManager.saveData('themeMode', 'dark'); notifyListeners(); } void setLightMode() async { _themeData = lightTheme; StorageManager.saveData('themeMode', 'light'); notifyListeners(); } }
Wrap your app with themeProvider and then apply theme using consumer. By doing so whenever you change the value of theme and call notify listeners widgets rebuild to sync changes.
Main.dart
void main() { return runApp(ChangeNotifierProvider<ThemeNotifier>( create: (_) => new ThemeNotifier(), child: MyApp(), )); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return Consumer<ThemeNotifier>( builder: (context, theme, _) => MaterialApp( theme: theme.getTheme(), home: Scaffold( appBar: AppBar( title: Text('Hybrid Theme'), ), body: Row( children: [ Container( child: FlatButton( onPressed: () => { print('Set Light Theme'), theme.setLightMode(), }, child: Text('Set Light Theme'), ), ), Container( child: FlatButton( onPressed: () => { print('Set Dark theme'), theme.setDarkMode(), }, child: Text('Set Dark theme'), ), ), ], ), ), ), ); } }
Here is the link to github repository.
Using Material App
MaterialApp( title: 'App Title', theme: ThemeData( brightness: Brightness.light, /* light theme settings */ ), darkTheme: ThemeData( brightness: Brightness.dark, /* dark theme settings */ ), themeMode: ThemeMode.dark, /* ThemeMode.system to follow system theme, ThemeMode.light for light theme, ThemeMode.dark for dark theme */ debugShowCheckedModeBanner: false, home: YourAppHomepage(), );
Using CupertinoApp
Detect the dark mode using, WidgetsBinding.instance?.window.platformBrightness
You may also have to listen for the brightness changes from the system in order to update in real-time using WidgetsBindingObserver
, and overriding, didChangePlatformBrightness();
CupertinoApp Example:
class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> with WidgetsBindingObserver { Brightness? _brightness; @override void initState() { WidgetsBinding.instance?.addObserver(this); _brightness = WidgetsBinding.instance?.window.platformBrightness; super.initState(); } @override void dispose() { WidgetsBinding.instance?.removeObserver(this); super.dispose(); } @override void didChangePlatformBrightness() { if (mounted) { setState(() { _brightness = WidgetsBinding.instance?.window.platformBrightness; }); } super.didChangePlatformBrightness(); } CupertinoThemeData get _lightTheme => CupertinoThemeData(brightness: Brightness.light, /* light theme settings */); CupertinoThemeData get _darkTheme => CupertinoThemeData( brightness: Brightness.dark, /* dark theme settings */, ); @override Widget build(BuildContext context) { return CupertinoApp( title: 'Demo App', theme: _brightness == Brightness.dark ? _darkTheme : _lightTheme, home: MyHomePage(title: 'Demo Home Page'), ); } }
You can use scoped_model, provider, bloc or get for seamless experience.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With