这个答案更进一步。它显示了如何加载和保存主题首选项,如何构建
ThemeData和如何从应用程序页面更改主题。
- 使用
shared_preferences
插件保存用户首选项(选择了哪个主题)。 - 使用整个Flutter框架中使用的“控制器模式”将当前选定的主题(及其更改)提供给您的应用。
- 使用可以
InheritedWidget
在应用的任何部分使用控制器。
控制器的外观如下:
import 'package:flutter/material.dart';import 'package:shared_preferences/shared_preferences.dart';/// provides the currently selected theme, saves changed theme preferences to diskclass ThemeController extends ChangeNotifier { static const themePrefKey = 'theme'; ThemeController(this._prefs) { // load theme from preferences on initialization _currentTheme = _prefs.getString(themePrefKey) ?? 'light'; } final SharedPreferences _prefs; String _currentTheme; /// get the current theme String get currentTheme => _currentTheme; void setTheme(String theme) { _currentTheme = theme; // notify the app that the theme was changed notifyListeners(); // store updated theme on disk _prefs.setString(themePrefKey, theme); } /// get the controller from any page of your app static ThemeController of(BuildContext context) { final provider = context.inheritFromWidgetOfExactType(ThemeControllerProvider) as ThemeControllerProvider; return provider.controller; }}/// provides the theme controller to any page of your appclass ThemeControllerProvider extends InheritedWidget { const ThemeControllerProvider({Key key, this.controller, Widget child}) : super(key: key, child: child); final ThemeController controller; @override bool updateShouldNotify(ThemeControllerProvider old) => controller != old.controller;}这是您将控制器和
InheritedWidget应用程序使用的方式:
void main() async { // load the shared preferences from disk before the app is started final prefs = await SharedPreferences.getInstance(); // create new theme controller, which will get the currently selected from shared preferences final themeController = ThemeController(prefs); runApp(MyApp(themeController: themeController));}class MyApp extends StatelessWidget { final ThemeController themeController; const MyApp({Key key, this.themeController}) : super(key: key); @override Widget build(BuildContext context) { // use AnimatedBuilder to listen to theme changes (listen to ChangeNotifier) // the app will be rebuilt when the theme changes return AnimatedBuilder( animation: themeController, builder: (context, _) { // wrap app in inherited widget to provide the ThemeController to all pages return ThemeControllerProvider( controller: themeController, child: MaterialApp( title: 'Flutter Demo', theme: _buildCurrentTheme(), home: MyHomePage(), ), ); }, ); } // build the flutter theme from the saved theme string ThemeData _buildCurrentTheme() { switch (themeController.currentTheme) { case "dark": return ThemeData( brightness: Brightness.dark, primarySwatch: Colors.orange, ); case "light": default: return ThemeData( brightness: Brightness.light, primarySwatch: Colors.blue, ); } }}class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: new AppBar(), body: Center( child: Column( children: <Widget>[ RaisedButton( onPressed: () { // thanks to the inherited widget, we can access the theme controller from any page ThemeController.of(context).setTheme('light'); }, child: Text('Light Theme'), ), RaisedButton( onPressed: () { ThemeController.of(context).setTheme('dark'); }, child: Text('Dark Theme'), ) ], ), ), ); }}


