我的目标是创建一个应用程序,用户可以选择他喜欢的主题。我保存了用户的选择与共享的首选项,这样我就可以加载它的下一个应用程序启动。用户可以选择:- 黑暗模式(独立于OS设置)-光明模式(独立于OS设置)-系统(根据OS设置在黑暗模式和光明模式之间切换)在BLoC的帮助下,我几乎实现了我想要的。但问题是我需要传递我的Bloc事件内部的亮度。为了获得我需要使用的系统(OS)亮度
MediaQuery.of(context).platformBrightness
但是Bloc在MaterialApp之前启动,因此MediaQuery不可用。当然,我可以稍后(从MaterialApp的子部件)传递亮度,但随后(例如,如果用户激活了暗模式)它会从亮到暗,但对用户可见的时间很短(因为在InitialState中,我在亮模式下传递)。
class MyApp extends StatelessWidget {
final RecipeRepository recipeRepository;
MyApp({Key key, @required this.recipeRepository})
: assert(recipeRepository != null),
super(key: key);
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<ThemeBloc>(create: (context) =>
ThemeBloc(),),
],
child: BlocBuilder<ThemeBloc, ThemeState>(
builder: (context, state){
return MaterialApp(
theme: state.themeData,
title: 'Flutter Weather',
localizationsDelegates: [
FlutterI18nDelegate(fallbackFile: 'en',),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
supportedLocales: [
const Locale("en"),
const Locale("de"),
],
home: Home(recipeRepository: recipeRepository),
);
},
),
);
}
}
ThemeBloc:
class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
@override
ThemeState get initialState =>
ThemeState(themeData: appThemeData[AppTheme.Bright]);
@override
Stream<ThemeState> mapEventToState(
ThemeEvent event,
) async* {
if (event is LoadLastTheme) {
ThemeData themeData = await _loadLastTheme(event.brightness);
yield ThemeState(themeData: themeData);
}
if (event is ThemeChanged) {
await _saveAppTheme(event.theme);
yield ThemeState(themeData: appThemeData[event.theme]);
}
}
Future<ThemeData> _loadLastTheme(Brightness brightness) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
String themeString = prefs.getString(SharedPrefKeys.appThemeKey);
print("saved theme: $themeString");
if ((prefs.getString(SharedPrefKeys.appThemeKey) != null) &&
themeString != "AppTheme.System") {
switch (themeString) {
case "AppTheme.Bright":
{
return appThemeData[AppTheme.Bright];
}
break;
///Selected dark mode
case "AppTheme.Dark":
{
return appThemeData[AppTheme.Dark];
}
break;
}
}
print("brightness: $brightness");
if (brightness == Brightness.dark) {
return appThemeData[AppTheme.Dark];
} else {
return appThemeData[AppTheme.Bright];
}
}
Future<void> _saveAppTheme(AppTheme appTheme) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString(SharedPrefKeys.appThemeKey, appTheme.toString());
}
}
2条答案
按热度按时间htrmnn0y1#
如果你一定要这样做,你可以直接从底层的window对象中获取
MediaQuery
数据,如下所示:但是,我强烈建议您考虑,如果您需要从您的区块中访问
MediaQuery
,您应该将BlocProvider
移动到MaterialApp
之后进行示例化,以便您可以正常访问MediaQuery
。sqxo8psd2#
从flutter3.10这个答案弃用,你应该使用这个