flutter_bloc切换主题

446 阅读1分钟
  • 效果:点击按钮,切换主题(light or dark
  • 思路:众所周知,MaterialAppthemeMode属性,可以方便的切换主题:
    • 条件为true,切换成ThemeMode.light
    • 为false,切换成ThemeMode.dark

那么,如何管理条件的状态呢?

今天它来了,flutter_bloc

  • pubspec.yaml文件中安装flutter_bloc,顺便安装equatable:
    • flutter_bloc: ^6.1.1 #状态管理框架
    • equatable: ^1.2.5 #增强组件相等性判断
  • VSCode中安装Bloc插件(Android Studio 里还是它)。
  • flutter_bloc的基本套路是:把Event添加到Bloc中,产生State
  • 插件会自动帮我们生成带有_bloc_event_state的三个文件:
    • _event(生产),比如按下按钮,产生ChangedEvent。isLight属性代表该事件的状态。
      class DemoChangedEvent extends DemoThemeEvent {
        final bool isLight;
        DemoChangedEvent({this.isLight});
       }
      
    • _bloc(加工)文件里,默认生成了mapEventToState 方法,它接收一个event事件,并且返回Stream<state>类型。我们就可以在任何时候拿到state的状态,判断当前的主题。
      @override
      Stream<DemoThemeState> mapEventToState(
       	DemoThemeEvent event,
       ) async* {
       	if (event is DemoChangedEvent) {
       		yield DemoThemeChaned(isLight: event.isLight);
       	}
       }
      
    • _state(产出),可以有我们想要的状态。为它添加isLight属性
      class DemoThemeChaned extends DemoThemeState {
        final bool isLight;
        DemoThemeChaned({this.isLight});
      
        @override
        List<Object> get props => [isLight];
        }
      
  • 首先重写initState方法,实例化对象,给Bloc添加isLighttrue的默认事件(默认ThemeMode.light)
@override
  void initState() {
    super.initState();
    _demoThemeBloc = DemoThemeBloc();
    _demoThemeBloc.add(DemoChangedEvent(isLight: true));
  }
  • 记住,有initState就要去重写dispose方法,像这样:
 @override
  void dispose() {
    _demoThemeBloc?.close();
    super.dispose();
  }
  • 那么,在build方法里
@override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => _demoThemeBloc,
      child: BlocBuilder<DemoThemeBloc, DemoThemeState>(
        builder: (context, state) {
          if (state is DemoThemeChaned) {
            return MaterialApp(
              debugShowCheckedModeBanner: false,
              theme: ThemeData.light(),//自定义样式
              darkTheme: ThemeData.dark(),//自定义样式
              themeMode: state.isLight ? ThemeMode.light : ThemeMode.dark,
              home: HomeScreen(),
            );
          } else {
            return SizedBox.shrink();
          }
        },
      ),
    );
  }
  • 最后点击按钮,将DemoChangedEvent添加到Bloc中,执行:
    onTap: () {
      BlocProvider.of<DemoThemeBloc>(context).add(
       DemoChangedEvent(isLight: !state.isLight),
      );
    },
    

Github地址