Last active
September 29, 2020 18:36
-
-
Save exavolt/c27d8791d8a7c025358fc5ff0fe4663b to your computer and use it in GitHub Desktop.
Switch theme mode (system, light, dark) dynamically
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:shared_preferences/shared_preferences.dart'; | |
// Wrap your application instance with this class. | |
// | |
// class MyApp extends StatelessWidget { | |
// // This widget is the root of your application. | |
// @override | |
// Widget build(BuildContext context) { | |
// return ThemeModeApp((BuildContext context, ThemeMode themeMode) { | |
// return MaterialApp( | |
// title: 'MyApp', | |
// theme: ThemeData.light(), | |
// darkTheme: ThemeData.dark(), | |
// home: HomeView(), | |
// themeMode: themeMode, | |
// ); | |
// }, | |
// } | |
// } | |
// | |
// And then somewhere in your app (e.g., settings view): | |
// | |
// ThemeModeApp.of(context).themeMode = ThemeMode.dark; // or ThemeMode.light or ThemeMode.system | |
// | |
// This is similar to dynamic_theme package but this focuses only on the theme mode. | |
class ThemeModeApp extends StatefulWidget { | |
final Function(BuildContext context, ThemeMode themeMode) appBuilder; | |
final String preferencesKeyPrefix; | |
ThemeModeApp(this.appBuilder, {this.preferencesKeyPrefix}); | |
static _ThemeModeAppState of(BuildContext context, {bool root = false}) => | |
root | |
? context.findRootAncestorStateOfType<_ThemeModeAppState>() | |
: context.findAncestorStateOfType<_ThemeModeAppState>(); | |
@override | |
_ThemeModeAppState createState() => _ThemeModeAppState(); | |
} | |
class _ThemeModeAppState extends State<ThemeModeApp> { | |
_ThemeModePreferences _preferences; | |
@override | |
Widget build(BuildContext context) { | |
return widget.appBuilder(context, _preferences.themeMode); | |
} | |
@override | |
void initState() { | |
super.initState(); | |
_preferences = _ThemeModePreferences(widget.preferencesKeyPrefix); | |
_preferences.addListener(_onPreferencesUpdate); | |
_preferences.loadState(); | |
} | |
@override | |
void dispose() { | |
_preferences.removeListener(_onPreferencesUpdate); | |
super.dispose(); | |
} | |
set themeMode(ThemeMode mode) { | |
_preferences.themeMode = mode; | |
} | |
ThemeMode get themeMode => _preferences.themeMode; | |
void _onPreferencesUpdate() { | |
setState(() {}); | |
} | |
} | |
// Do NOT use this in a Provider | |
class _ThemeModePreferences extends ChangeNotifier { | |
final String preferencesKeyPrefix; | |
_ThemeModePreferences(this.preferencesKeyPrefix); | |
bool _stateLoaded = false; | |
ThemeMode _themeMode = ThemeMode.system; | |
ThemeMode get themeMode => _themeMode; | |
set themeMode(ThemeMode value) { | |
_storeThemeMode(value); | |
} | |
void _storeThemeMode(ThemeMode value) async { | |
if (_themeMode == value) { | |
return; | |
} | |
SharedPreferences prefs = await SharedPreferences.getInstance(); | |
_themeMode = value; | |
await prefs.setInt( | |
_preferenceKey(_themeModePreferenceFieldName), _themeMode.index); | |
notifyListeners(); | |
} | |
Future loadState() async { | |
if (_stateLoaded) { | |
return; | |
} | |
_stateLoaded = true; | |
SharedPreferences prefs = await SharedPreferences.getInstance(); | |
final themeModeIndex = | |
prefs.getInt(_preferenceKey(_themeModePreferenceFieldName)); | |
if (themeModeIndex != null) { | |
final themeMode = ThemeMode.values[themeModeIndex]; | |
if (_themeMode != themeMode) { | |
_themeMode = themeMode; | |
notifyListeners(); | |
} | |
} | |
} | |
static const _themeModePreferenceFieldName = 'themeMode'; | |
String _preferenceKey(String fieldName) { | |
if (preferencesKeyPrefix?.isNotEmpty == true) { | |
if (preferencesKeyPrefix.endsWith('.')) { | |
return preferencesKeyPrefix + fieldName; | |
} | |
return preferencesKeyPrefix + '.' + fieldName; | |
} | |
if (preferencesKeyPrefix == null) { | |
return 'app.' + fieldName; | |
} | |
return fieldName; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment