Флаттер, как получить яркость без MediaQuery? - PullRequest
0 голосов
/ 23 февраля 2020

Моя цель - создать приложение, в котором пользователь сможет выбрать предпочитаемую тему. Я сохраняю выбор пользователя с общими настройками, чтобы я мог загрузить его при следующем запуске приложения. Пользователь может выбрать: - Темный режим (независимо от настроек ОС) - Светлый режим (независимо от настроек ОС) - Система (Переключение между темным режимом и Светлым режимом в зависимости от настроек ОС) С помощью BLo C Я почти достиг того, чего хочу. Но проблема в том, что мне нужно передать яркость внутри моего события Blo c. И чтобы получить яркость системы (ОС), мне нужно использовать

MediaQuery.of(context).platformBrightness

Но Blo c запускается до 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),
          );
        },
      ),
    );
  }
}

ThemeBlo c:

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());
  }
}

1 Ответ

0 голосов
/ 23 февраля 2020

Если вам абсолютно необходимо сделать это так, вы можете MediaQuery получить данные непосредственно из низкоуровневого оконного объекта, например:

final brightness = MediaQueryData.fromWindow(WidgetsBinding.instance.window).platformBrightness;

Однако я настоятельно рекомендую вам учесть, что если вы вам нужен доступ к MediaQuery из вашего блока c, вместо этого вам нужно переместить BlocProvider, чтобы получить экземпляр после вашего MaterialApp, чтобы вы могли получить доступ к MediaQuery в обычном режиме.

...