Flutter 实现主题切换,适配暗黑模式!

先看一张效果图

实现大致思路:
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,
          ),
        );
      })
    );
  }
}

你可能感兴趣的:(Flutter)