Flutter中ThemeData的ColorScheme使用问题:自定义主题属性不生效
Flutter明暗主题属性不生效问题解决
问题场景
配置了Flutter应用的明暗两种主题模式,在MaterialApp中指定了theme和darkTheme,但scaffoldBackgroundColor、AppBarTheme、InputDecorationTheme均未生效:
- scaffoldBackgroundColor仍显示默认浅蓝色
- AppBar中无法使用自定义ColorScheme的颜色
- InputDecoration的fillColor和hintStyle颜色被忽略
相关核心代码如下:
MaterialApp配置
return MaterialApp( initialRoute: '/', routes: routesHandler, theme: lightThemeData(context), darkTheme: darkThemeData(context), debugShowCheckedModeBanner: false, );
自定义ColorScheme
ColorScheme lightThemeColors(context) { return const ColorScheme( brightness: Brightness.light, primary: Color(0xFF202020), onPrimary: Color(0xFF505050), secondary: Color(0xFFBBBBBB), onSecondary: Color(0xFFEAEAEA), error: Color(0xFFF32424), onError: Color(0xFFF32424), background: Color(0xFFF1F2F3), onBackground: Color(0xFFFFFFFF), surface: Color(0xFF54B435), onSurface: Color(0xFF54B435), ); } ColorScheme darkThemeColors(context) { return const ColorScheme( brightness: Brightness.dark, primary: Color(0xFFF1F2F3), onPrimary: Color(0xFFFFFFFF), secondary: Color(0xFFBBBBBB), onSecondary: Color(0xFFEAEAEA), error: Color(0xFFF32424), onError: Color(0xFFF32424), background: Color(0xFF202020), onBackground: Color(0xFF505050), surface: Color(0xFF54B435), onSurface: Color(0xFF54B435), ); }
原ThemeData实现(存在问题)
ThemeData lightThemeData(BuildContext context) { return ThemeData( scaffoldBackgroundColor: Theme.of(context).colorScheme.background, textTheme: textTheme(context), appBarTheme: appBarTheme(context), inputDecorationTheme: inputDecorationData(context), colorScheme: lightThemeColors(context), ); } ThemeData darkThemeData(BuildContext context) { return ThemeData( scaffoldBackgroundColor: Theme.of(context).colorScheme.background, textTheme: textTheme(context), appBarTheme: appBarTheme(context), inputDecorationTheme: inputDecorationData(context), colorScheme: darkThemeColors(context), ); }
原AppBarTheme和InputDecorationTheme实现
AppBarTheme appBarTheme(context) { return AppBarTheme( backgroundColor: Theme.of(context).colorScheme.background, titleTextStyle: Theme.of(context).textTheme.headline5?.copyWith(color: Theme.of(context).colorScheme.primary), ); }
InputDecorationTheme inputDecorationData(context) { return InputDecorationTheme( filled: true, fillColor: Theme.of(context).colorScheme.onBackground, hintStyle: Theme.of(context).textTheme.bodyText1?.copyWith(color: Theme.of(context).colorScheme.onSecondary), ); }
问题原因
核心问题是构建ThemeData时,使用Theme.of(context)获取的是当前上下文的默认主题,而非正在创建的自定义ColorScheme。此时新的ThemeData还未被MaterialApp应用到上下文,所以所有依赖Theme.of(context)的属性都会读取默认主题值,导致自定义配置失效。
解决方案
修改ThemeData的构建逻辑,先创建自定义ColorScheme,然后直接基于这个Scheme来设置各个主题属性,不再通过Theme.of(context)获取:
1. 修改ThemeData函数
ThemeData lightThemeData(BuildContext context) { // 先创建自定义ColorScheme final colorScheme = lightThemeColors(context); // 基于自定义Scheme构建ThemeData return ThemeData( scaffoldBackgroundColor: colorScheme.background, textTheme: textTheme(context), appBarTheme: appBarTheme(colorScheme, context), inputDecorationTheme: inputDecorationData(colorScheme, context), colorScheme: colorScheme, ); } ThemeData darkThemeData(BuildContext context) { final colorScheme = darkThemeColors(context); return ThemeData( scaffoldBackgroundColor: colorScheme.background, textTheme: textTheme(context), appBarTheme: appBarTheme(colorScheme, context), inputDecorationTheme: inputDecorationData(colorScheme, context), colorScheme: colorScheme, ); }
2. 修改AppBarTheme函数
接收自定义ColorScheme作为参数,直接使用它的颜色:
AppBarTheme appBarTheme(ColorScheme colorScheme, BuildContext context) { return AppBarTheme( backgroundColor: colorScheme.background, titleTextStyle: Theme.of(context).textTheme.headline5?.copyWith(color: colorScheme.primary), ); }
3. 修改InputDecorationTheme函数
同样接收自定义ColorScheme参数:
InputDecorationTheme inputDecorationData(ColorScheme colorScheme, BuildContext context) { return InputDecorationTheme( filled: true, fillColor: colorScheme.onBackground, hintStyle: Theme.of(context).textTheme.bodyText1?.copyWith(color: colorScheme.onSecondary), ); }
额外说明
如果textTheme也需要依赖自定义ColorScheme,同样可以把colorScheme参数传递过去,避免使用Theme.of(context)读取默认值。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

