Flutter中在MaterialApp上下文外配置textTheme遇未定义context错误
解决Flutter主题切换中Theme.of(context)无上下文的问题
问题根源
MyThemes是静态类,没有BuildContext,因此无法直接调用Theme.of(context)获取主题配置。原代码能正常运行,是因为Theme.of(context)用的是MaterialApp父级上下文的默认主题(此时MaterialApp自身的主题还未创建)。
解决方案
方案1:将主题定义改为接收Context的静态方法
修改MyThemes类,把静态主题属性改成带BuildContext参数的静态方法,在创建MaterialApp时传入上下文:
class MyThemes { static ThemeData darkTheme() { return ThemeData( scaffoldBackgroundColor: Colors.grey.shade900, colorScheme: const ColorScheme.dark(), ); } static ThemeData lightTheme(BuildContext context) { return ThemeData( scaffoldBackgroundColor: Colors.white, colorScheme: const ColorScheme.light(), dividerColor: Colors.black, textTheme: GoogleFonts.aguafinaScriptTextTheme( Theme.of(context).textTheme, ), ); } }
然后在MaterialApp的builder中调用方法并传入context:
@override Widget build(BuildContext context) => ChangeNotifierProvider( create: (context) => ThemeProvider(), builder: (context, _) { final themeProvider = Provider.of<ThemeProvider>(context); return MaterialApp( scaffoldMessengerKey: Utils.messengerKey, navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, themeMode: themeProvider.themeMode, darkTheme: MyThemes.darkTheme(), theme: MyThemes.lightTheme(context), home: MainPage(), ); }, );
方案2:直接使用默认主题的TextTheme
如果不需要依赖父级上下文的主题配置,可以直接用Flutter默认的浅色主题TextTheme替代Theme.of(context).textTheme,和原代码行为一致:
class MyThemes { static final darkTheme = ThemeData( scaffoldBackgroundColor: Colors.grey.shade900, colorScheme: const ColorScheme.dark(), ); static final lightTheme = ThemeData( scaffoldBackgroundColor: Colors.white, colorScheme: const ColorScheme.light(), dividerColor: Colors.black, textTheme: GoogleFonts.aguafinaScriptTextTheme( ThemeData.light().textTheme, // 使用默认浅色主题的TextTheme ), ); }
方案3:在MaterialApp中扩展主题
保持MyThemes只定义基础主题,将TextTheme的配置移到MaterialApp的theme参数中,利用copyWith扩展:
class MyThemes { static final darkTheme = ThemeData( scaffoldBackgroundColor: Colors.grey.shade900, colorScheme: const ColorScheme.dark(), ); static final lightTheme = ThemeData( scaffoldBackgroundColor: Colors.white, colorScheme: const ColorScheme.light(), dividerColor: Colors.black, ); }
然后在MaterialApp中配置:
@override Widget build(BuildContext context) => ChangeNotifierProvider( create: (context) => ThemeProvider(), builder: (context, _) { final themeProvider = Provider.of<ThemeProvider>(context); return MaterialApp( scaffoldMessengerKey: Utils.messengerKey, navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, themeMode: themeProvider.themeMode, darkTheme: MyThemes.darkTheme, theme: MyThemes.lightTheme.copyWith( textTheme: GoogleFonts.aguafinaScriptTextTheme( Theme.of(context).textTheme, ), ), home: MainPage(), ); }, );
内容的提问来源于stack exchange,提问作者taha khamis
相关产品推荐
相关产品推荐

