如何在Flutter中使用bloc切换主题?

4

我刚接触Flutter和bloc。我正在使用bloc状态管理制作一个可以根据系统主题更改主题的应用程序。现在它运行良好,但我需要一个可以覆盖主题的开关。我是通过观看YouTube教程来制作这个应用程序的。 有没有办法创建一个可以更改主题的开关。

主题Cubit

class ThemeCubit extends Cubit<ThemeState> {
  ThemeCubit() : super(ThemeState(themeMode: ThemeMode.light)) {
    updateAppTheme();
  }

  void updateAppTheme() {
    final Brightness currentBrightness = AppTheme.currentSystemBrightness;
    currentBrightness == Brightness.light
        ? _setTheme(ThemeMode.light)
        : _setTheme(ThemeMode.dark);
  }

  void _setTheme(ThemeMode themeMode) {
    AppTheme.setStatusBarAndNavigationBarColor(themeMode);
    emit(ThemeState(themeMode: themeMode));
  }
}

主题状态

class ThemeState {
  final ThemeMode themeMode;

  ThemeState({@required this.themeMode});
}

这是 main.dart 的代码

void main() {
  Bloc.observer = AppBlocObserver();
  runApp(DevicePreview(
    builder: (context) => App(),
    enabled: false,
    plugins: [
      const ScreenshotPlugin(),
    ],
  ));
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider<ThemeCubit>(
          create: (context) => ThemeCubit(),
        ),
      ],
      child: MchatsApp(),
    );
  }
}

class MchatsApp extends StatefulWidget {
  const MchatsApp({
    Key key,
  }) : super(key: key);

  @override
  _MchatsAppState createState() => _MchatsAppState();
}

class _MchatsAppState extends State<MchatsApp> with WidgetsBindingObserver {
  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangePlatformBrightness() {
    context.read<ThemeCubit>().updateAppTheme();
    super.didChangePlatformBrightness();
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        return OrientationBuilder(
          builder: (context, orientation) {
            SizerUtil().init(constraints, orientation);

            return MaterialApp(
              locale: DevicePreview.locale(context),
              builder: DevicePreview.appBuilder,
              title: Strings.appTitle,
              theme: AppTheme.lightTheme,
              darkTheme: AppTheme.darkTheme,
              themeMode: context.select(
                  (ThemeCubit themeCubit) => themeCubit.state.themeMode),
              debugShowCheckedModeBanner: false,
              initialRoute: AppRouter.root,
              onGenerateRoute: AppRouter.onGenerateRoute,
            );
          },
        );
      },
    );
  }
}
1个回答

2

是的,你可以

在Switch Widget的onChanged函数中调用你的cubit中的updateAppTheme()函数

context.read<ThemeCubit>().updateAppTheme();

Builder(
builder:(context){
bool isDark= context.select(
                  (ThemeCubit themeCubit) => themeCubit.state.themeMode)==ThemeMode.dark?true:false;
return Switch(value: isDark, onChanged: (value) {
context.read<ThemeCubit>().updateAppTheme();}
);
})

它不起作用。 Switch( activeColor: Colors.black, value: false, onChanged: (value) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text('主题更改'), duration: Duration(milliseconds: 700), )); setState(() { context.read<ThemeCubit>().updateAppTheme(); _switchValue = value; }); }, ), - Sunny Rahi
onChanged函数的返回值始终为false,因为它没有状态。 - Islomkhuja Akhrarov
等一下,我会为你的问题编写特定的代码。 - Islomkhuja Akhrarov
它显示了这个,但主题没有改变。 I/flutter(5260):onChange--ThemeCubit,Change {currentState:Instance of 'ThemeState',nextState:Instance of 'ThemeState'} - Sunny Rahi
@islamakhrarov 我尝试了你的代码片段,但是切换器在切换时表现得像被禁用了一样。你能提供带有开关的计数器UI的完整代码吗?这样更容易理解。 - Maruf Hassan
@MarufHassan 你好,我希望能够放上整个代码,但问题是如何解决错误。我建议你开一个新的问题并私信我。 目前,我可以推荐你观看这个视频:https://www.youtube.com/watch?v=YYbhkg-W8Mg&t=438s - Islomkhuja Akhrarov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接