Flutter深色主题文本颜色不生效,如何用单个TextTheme+GetX适配双主题?
问题根源
你当前的问题出在静态TextTheme初始化时就固定了颜色值——MyTextTheme.myTextTheme是静态变量,第一次加载时就根据当时的Get.isDarkMode状态确定了颜色,后续切换主题时这个变量不会重新生成,所以深色模式下文本颜色还是初始的浅色值(或相反),自然不生效。
解决方案
以下是几种无需维护两个独立TextTheme类的实现方式,按实用性排序:
方案一:将TextTheme改为动态生成的方法(最直接)
把静态变量改成静态方法,每次获取时都根据当前Get.isDarkMode状态重新构建TextTheme,确保亮色/深色主题调用时拿到对应颜色的样式:
修改MyTextTheme类:
class MyTextTheme { static const String fontFamily = 'Vazir'; // 改成静态方法,每次调用都生成新的TextTheme static TextTheme getTextTheme() { return TextTheme( titleLarge: TextStyle( fontSize: 25, fontWeight: FontWeight.w700, color: Get.isDarkMode ? const Color.fromARGB(255, 255, 242, 231) : const Color.fromARGB(255, 137, 116, 253), ), // 其他文本样式同理 ); } }
更新主题代码,调用方法替代静态变量:
static final lightTheme = ThemeData( // ...其他配置(buttonTheme、primaryColor等) textTheme: MyTextTheme.getTextTheme(), ); static final darkTheme = ThemeData( // ...其他配置(elevatedButtonTheme、colorScheme等) textTheme: MyTextTheme.getTextTheme(), );
注意:切换主题后需要确保页面重建(比如用
Get.forceAppUpdate()或依赖主题变化的Obx),这样会重新调用getTextTheme()获取最新颜色。
方案二:贴合GetX生态的响应式实现
如果希望主题切换时文本样式自动更新,无需手动重建页面,可以结合GetX的响应式变量:
- 在主题管理Controller中添加响应式TextTheme:
class ThemeController extends GetxController { final RxBool isDarkMode = false.obs; // 响应式TextTheme,随isDarkMode变化自动更新 final Rx<TextTheme> currentTextTheme = Rx<TextTheme>(_buildInitialTextTheme()); void toggleTheme() { isDarkMode.value = !isDarkMode.value; // 更新全局主题 Get.changeTheme(isDarkMode.value ? AppThemes.darkTheme : AppThemes.lightTheme); // 同步更新TextTheme currentTextTheme.value = _buildTextTheme(isDarkMode.value); } static TextTheme _buildInitialTextTheme() { return TextTheme( titleLarge: TextStyle( fontSize: 25, fontWeight: FontWeight.w700, color: Get.isDarkMode ? const Color.fromARGB(255, 255, 242, 231) : const Color.fromARGB(255, 137, 116, 253), ), ); } static TextTheme _buildTextTheme(bool isDark) { return TextTheme( titleLarge: TextStyle( fontSize: 25, fontWeight: FontWeight.w700, color: isDark ? const Color.fromARGB(255, 255, 242, 231) : const Color.fromARGB(255, 137, 116, 253), ), // 其他样式 ); } }
- 页面中通过
Obx监听并使用:
final themeController = Get.find<ThemeController>(); // 在Widget中使用响应式样式 Obx(() => Text( "示例标题", style: themeController.currentTextTheme.value.titleLarge, ));
方案三:关联Material ColorScheme(符合设计规范)
不硬编码颜色,而是通过ThemeData的colorScheme关联文本颜色,亮色/深色主题的colorScheme不同,文本颜色自动适配:
修改MyTextTheme,接收ColorScheme参数:
class MyTextTheme { static const String fontFamily = 'Vazir'; // 根据传入的ColorScheme生成对应样式 static TextTheme getTextTheme(ColorScheme colorScheme) { return TextTheme( titleLarge: TextStyle( fontSize: 25, fontWeight: FontWeight.w700, color: colorScheme.onSurface, // 关联colorScheme的对应颜色 ), // 其他文本样式可关联colorScheme.onBackground、colorScheme.onPrimary等 ); } }
更新主题代码,配置colorScheme并传入:
static final lightTheme = ThemeData( colorScheme: ColorScheme.fromSwatch( backgroundColor: Colors.white, onSurface: const Color.fromARGB(255, 137, 116, 253), // 浅色主题文本颜色 ), // ...其他配置 textTheme: MyTextTheme.getTextTheme(lightTheme.colorScheme), ); static final darkTheme = ThemeData( colorScheme: ColorScheme.dark().copyWith( onSurface: const Color.fromARGB(255, 255, 242, 231), // 深色主题文本颜色 ), // ...其他配置 textTheme: MyTextTheme.getTextTheme(darkTheme.colorScheme), );
这种方式遵循Material设计的颜色系统,后续修改主题颜色只需调整colorScheme,无需改动TextTheme。
内容的提问来源于stack exchange,提问作者Hossein Saeedi
相关产品推荐
相关产品推荐

