Flutter中实现亮色/暗色/系统主题切换
Flutter中实现亮色/暗色/系统主题切换
嘿,看起来你已经搭好了主题切换的基础架子!要实现亮色、暗色和跟随系统这三个选项,咱们得调整下现有代码,让它既能记住用户的选择,又能跟着系统主题变化自动更新。下面一步步来完善:
第一步:升级你的ThemeChanger Provider
原来的ThemeChanger只存了固定的ThemeData,没法应对系统主题变化和用户的不同选择。咱们改成记录用户的主题模式偏好,再根据这个偏好动态生成对应的主题:
import 'package:flutter/material.dart'; // 直接用Flutter自带的ThemeMode来表示主题偏好选项就够用啦 enum ThemePreference { light, dark, system } class ThemeChanger with ChangeNotifier { // 记录用户选择的主题偏好 ThemePreference _preference = ThemePreference.system; // 缓存系统当前的主题模式 ThemeMode _systemThemeMode = ThemeMode.light; ThemeChanger() { // 初始化时获取系统当前主题,并监听后续变化 _initSystemThemeListener(); } // 给外部提供当前偏好的getter ThemePreference get preference => _preference; // 获取当前应该使用的主题模式 ThemeMode get currentThemeMode { switch (_preference) { case ThemePreference.light: return ThemeMode.light; case ThemePreference.dark: return ThemeMode.dark; case ThemePreference.system: return _systemThemeMode; } } // 获取对应的ThemeData(这里可以替换成你自定义的亮色/暗色主题) ThemeData get currentTheme { switch (currentThemeMode) { case ThemeMode.light: return ThemeData.light(useMaterial3: true); case ThemeMode.dark: return ThemeData.dark(useMaterial3: true); default: return ThemeData.light(useMaterial3: true); } } // 设置用户的主题偏好 void setThemePreference(ThemePreference newPreference) { _preference = newPreference; notifyListeners(); } // 监听系统主题变化的方法 void _initSystemThemeListener() { final window = WidgetsBinding.instance.window; // 初始化系统当前主题 _updateSystemTheme(window.platformBrightness); // 监听系统主题变更 window.onPlatformBrightnessChanged = () { _updateSystemTheme(window.platformBrightness); notifyListeners(); }; } void _updateSystemTheme(Brightness brightness) { _systemThemeMode = brightness == Brightness.dark ? ThemeMode.dark : ThemeMode.light; } }
第二步:在main.dart中配置Provider
要让整个App都能访问到ThemeChanger,得把它放到顶层的Provider里:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'home.dart'; import 'theme_changer.dart'; void main() { runApp( ChangeNotifierProvider( create: (context) => ThemeChanger(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return Consumer<ThemeChanger>( builder: (context, themeChanger, child) { return MaterialApp( title: '主题切换Demo', theme: themeChanger.currentTheme, home: const HomePage(), ); }, ); } }
第三步:在HomePage中添加主题切换UI
现在咱们给HomePage加个切换选项,比如用下拉菜单让用户直观选择:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'theme_changer.dart'; class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { final themeChanger = Provider.of<ThemeChanger>(context); return Scaffold( appBar: AppBar( title: const Text('AppBar'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('选择主题模式:'), const SizedBox(height: 16), DropdownButton<ThemePreference>( value: themeChanger.preference, items: const [ DropdownMenuItem( value: ThemePreference.light, child: Text('亮色主题'), ), DropdownMenuItem( value: ThemePreference.dark, child: Text('暗色主题'), ), DropdownMenuItem( value: ThemePreference.system, child: Text('跟随系统'), ), ], onChanged: (value) { if (value != null) { themeChanger.setThemePreference(value); } }, ), ], ), ), ); } }
小提醒
- 如果你有自己定制的亮色/暗色主题,直接替换
currentTheme里的ThemeData.light()和ThemeData.dark()就行。 - 这样改造后,用户选择「跟随系统」时,App会自动同步手机的系统主题变化,另外两个选项则会固定使用对应模式。
备注:内容来源于stack exchange,提问作者ira
相关产品推荐
相关产品推荐

