- 效果:点击按钮,切换主题(
lightordark) - 思路:众所周知,
MaterialApp的themeMode属性,可以方便的切换主题:- 条件为true,切换成
ThemeMode.light - 为false,切换成
ThemeMode.dark
- 条件为true,切换成
那么,如何管理条件的状态呢?
今天它来了,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添加isLight为true的默认事件(默认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), ); },