先看一张效果图
实现大致思路:
1、使用一个状态管理器,来实现主题的切换。这里使用的是redux。版本:flutter_redux: ^0.6.0。
2、使用本地存储来记录选择的模式,0:浅色模式。1:深色模式。2:跟随系统。本地存储使用的是:shared_preferences: 0.5.6。
3、在打开APP的时候,根据本地存储的标志位,来选择具体的AppTheme。
**首先写一个 全局的状态管理类WSState.dart。
import 'package:ws/redux/theme_redux.dart';
/**
* Redux全局State
*/
///全局Redux store 的对象,保存State数据
class WSState{
///主题数据
/// 深色模式 0: 关闭 1: 开启 2: 随系统
int darkMode;
WSState({this.darkMode});
}
WSState appReducer(WSState state,action){
return WSState(
///通过 ThemeDataReducer 将 WSState 内的 themeData 和 action 关联在一起
darkMode:DarkModelReducer(state.darkMode,action),
);
}
其次在编写我们主题的事件的状态管理,theme_redux.dart
import 'package:redux/redux.dart';
/*
* 主题事件的状态管理
*
*/
//通过flutter_redux的combineReducers. 实现Reducer方法
final DarkModelReducer =combineReducers<int>([
//将Action、处理Action的方法 state绑定
TypedReducer<int,RefreshThemeDataAction>(_refresh),
]);
//定义处理Action 行为的方法,返回新的State
int _refresh(int darkMode, action){
darkMode=action.darkMode;
return darkMode;
}
///定义一个Action类
///将该 Action 在 Reducer 中与处理该Action的方法绑定
class RefreshThemeDataAction{
final int darkMode;
RefreshThemeDataAction(this.darkMode);
}
```javascript
实现切换主题的页面,check_theme.dart
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:ws/common/config/config.dart';
import 'package:ws/common/local/local_storage.dart';
import 'package:ws/redux/theme_redux.dart';
import 'package:ws/redux/ws_state.dart';
class CheckTheme extends StatefulWidget{
@override
State<StatefulWidget> createState() =>_CheckThemeState();
}
class _CheckThemeState extends State<CheckTheme>{
var darkMap=<int,String>{
// Key: Value
0: '浅色模式',
1: '深色模式',
2: '跟随系统'
};
int darkModel=2;
@override
void initState() {
// TODO: implement initState
super.initState();
///读取主题
initTheme();
}
initTheme()async{
String themeIndex = await LocalStorage.get(Config.DARK_MODEL);
if (themeIndex != null && themeIndex.length != 0) {
setState(() {
darkModel=int.parse(themeIndex);
});
}else{
setState(() {
darkModel=2;
});
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return StoreBuilder<WSState>(
builder:(context,store){
return Scaffold(
appBar: AppBar(
title: Text("${darkMap[darkModel]}"),
),
body: ListView.separated(
itemCount: 3,
separatorBuilder: (context,index){
return Divider();
},
itemBuilder: (context,index){
return ListTile(
title: Text(darkMap[index]),
trailing: Offstage(
offstage:darkModel==index?false:true ,
child: Icon(Icons.check),
),
onTap: (){
setState(() {
darkModel=index;
});
store.dispatch(new RefreshThemeDataAction(index));
LocalStorage.save(Config.DARK_MODEL, index.toString());
Navigator.pop(context);
},
);
},
),
);
}
);
}
}
准备工作都做好之后我们就编写启动APP的时候,通过选择的标志位来实现主题的选择。app.dart
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => _AppState();
}
class _AppState extends State<MyApp> with HttpErrorListener {
/// 创建Store,引用WSState 中的 appReducer 实现 reducer 方法
/// initialState 初始化 state
final store=Store<WSState>(
appReducer,
initialState: WSState(
darkMode: 0,
)
);
@override
void initState() {
// TODO: implement initState
super.initState();
///读取主题
initTheme();
}
initTheme()async{
String themeIndex = await LocalStorage.get(Config.DARK_MODEL);
if (themeIndex != null && themeIndex.length != 0) {
store.dispatch(new RefreshThemeDataAction(int.parse(themeIndex)));
}else{
store.dispatch(new RefreshThemeDataAction(2));
}
}
@override
Widget build(BuildContext context) {
/// 使用 flutter_redux 做全局状态共享
/// 使用 StoreProvider 应用store
return StoreProvider(
store: store,
child:StoreBuilder<WSState>(builder: (context, store) {
return store.state.darkMode == 2
? MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
darkTheme: ThemeData.dark(),
)
: MaterialApp(
theme: store.state.darkMode == 1
? ThemeData.dark()
: ThemeData(
primarySwatch: Colors.blue,
),
);
})
);
}
}