Flutter自定义明暗主题切换异常:切换显示异常重启后恢复
Flutter 自定义主题切换后显示异常,重启后恢复正常问题解决
问题描述
在Flutter中开发自定义明暗双主题,切换主题时部分颜色显示异常,但重启应用后主题显示恢复正常。
效果对比
- 切换主题后异常显示:

- 重启应用后正常显示:

相关代码实现
主页面代码
ThemeController themecontroller = Get.put(ThemeController()); return GetMaterialApp( title: 'where to go', debugShowCheckedModeBanner: false, translations: Messages(), locale: mycontroller.initlang, theme: themecontroller.themedata ? Themes.customDarkTheme : Themes.customLightTheme, darkTheme: Themes.customDarkTheme, home: const SplashScreen());
自定义主题类代码
class Themes { static ThemeData customLightTheme = ThemeData( brightness: Brightness.light, colorScheme: ColorScheme.light( background: Colors.white, primary: Colors.white, onPrimary: Colors.grey[600]!, secondary: Colors.white, onSecondary: Colors.grey[600]!, surface: Colors.white, onSurface: Colors.deepPurple, tertiary: Colors.black, onTertiary: const Color.fromRGBO(96, 102, 214, 1), )); static ThemeData customDarkTheme = ThemeData( brightness: Brightness.dark, colorScheme: ColorScheme.dark( background: Colors.black, primary: Colors.white.withOpacity(0.87), onPrimary: Colors.white.withOpacity(0.60), secondary: Colors.grey[800]!, onSecondary: Colors.white.withOpacity(0.38), surface: const Color(0xff121212), onSurface: Colors.white.withOpacity(0.87), tertiary: Colors.white.withOpacity(0.80), onTertiary: const Color(0xff121212), )); }
设置页面代码
Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( onPressed: () { Get.off(const HomePage()); }, icon: const Icon( Icons.arrow_back_outlined, ), ), iconTheme: const IconThemeData(color: Colors.white), title: Text( 'Settings'.tr, style: TextStyle( fontSize: 25.0, fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary), ), flexibleSpace: Container( decoration: Get.isDarkMode ? const BoxDecoration(color: Color(0xff121212)) : const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: <Color>[ Color.fromRGBO(78, 84, 200, 1.0), Color.fromRGBO(127, 133, 239, 1.0), ]), ), )), body: Container( padding: const EdgeInsets.all(8.0), child: ListView( children: [ const SizedBox( height: 40.0, ), Row( children: [ Icon( Icons.person, color: Theme.of(context).colorScheme.onSurface, ), const SizedBox( width: 10.0, ), Text('Account'.tr, style: TextStyle( color: Theme.of(context).colorScheme.tertiary, fontSize: 20.0, fontWeight: FontWeight.bold)) ], ), const Divider( height: 20.0, thickness: 1.0, ), const SizedBox( height: 10.0, ), buildAccountOption(context, "Change Password".tr, 0), buildAccountOption(context, "Language".tr, 1), buildAccountOption(context, "Privacy and Security".tr, 2), buildAccountOption(context, "Delete Account".tr, 3), buildAccountOption(context, "Logout".tr, 4), const SizedBox( height: 40.0, ), Row( children: [ Icon( Icons.theater_comedy, color: Theme.of(context).colorScheme.onSurface, ), const SizedBox( width: 10.0, ), Text('Theme', style: TextStyle( fontSize: 20.0, fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.tertiary)) ], ), const Divider( height: 20.0, thickness: 1.0, ), const SizedBox( height: 10.0, ), buildNotificationOption2( "Theme Dark", valNotify1, onChangedFunc1, ), /* buildNotificationOption1(), const SizedBox( height: 10.0, ), Center( child: OutlinedButton( style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 40.0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0), )), onPressed: () {}, child: const Text( "Save", style: TextStyle( fontSize: 16.0, color: Colors.black, letterSpacing: 2.2), ), ), ) */ ], ), ), ); }
问题原因与解决方案
核心问题
GetMaterialApp配置逻辑冲突:同时设置theme和darkTheme,但theme直接根据控制器状态切换明暗主题,导致Flutter主题更新机制混乱,无法同步更新所有组件的主题上下文。
修复方案
规范主题配置
保持theme为固定浅色主题,darkTheme为固定深色主题,通过themeMode控制当前主题模式。修改主页面代码:ThemeController themecontroller = Get.put(ThemeController()); return GetMaterialApp( title: 'where to go', debugShowCheckedModeBanner: false, translations: Messages(), locale: mycontroller.initlang, theme: Themes.customLightTheme, darkTheme: Themes.customDarkTheme, themeMode: themecontroller.themedata ? ThemeMode.dark : ThemeMode.light, home: const SplashScreen());确保主题状态可响应
控制器中使用Rx变量存储主题状态,确保状态变化能触发UI更新:class ThemeController extends GetxController { RxBool isDarkMode = false.obs; void toggleTheme() { isDarkMode.value = !isDarkMode.value; // 可选:用GetStorage持久化状态 // GetStorage().write('isDarkMode', isDarkMode.value); } @override void onInit() { super.onInit(); // 可选:从本地恢复状态 // isDarkMode.value = GetStorage().read('isDarkMode') ?? false; } }更新设置页切换逻辑
在设置页的切换回调中调用控制器的主题切换方法:void onChangedFunc1(bool value) { themecontroller.toggleTheme(); }移除硬编码颜色
替换设置页中硬编码的颜色(如IconThemeData(color: Colors.white)),改用主题色:iconTheme: IconThemeData(color: Theme.of(context).colorScheme.onPrimary),
修改完成后,切换主题时所有组件颜色会即时同步更新,无需重启应用。
内容的提问来源于stack exchange,提问作者Emad Younan
相关产品推荐
相关产品推荐

