Flutter实战之主题切换

预设主题样式

这里只做了主题颜色的改变。也可以修改其他的ThemeData

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Map<String, Color> themeColorMap = {
'gray': Colors.grey,
'blue': Colors.blue,
'blueAccent': Colors.blueAccent,
'cyan': Colors.cyan,
'deepPurple': Colors.purple,
'deepPurpleAccent': Colors.deepPurpleAccent,
'deepOrange': Colors.orange,
'green': Colors.green,
'indigo': Colors.indigo,
'indigoAccent': Colors.indigoAccent,
'orange': Colors.orange,
'purple': Colors.purple,
'pink': Colors.pink,
'red': Colors.red,
'teal': Colors.teal,
'black': Colors.black,
};

使用Provider全局管理

定义主题样式的Provider。 数据改变时,使用notifyListeners通知组件更新

1
2
3
4
5
6
7
8
9
10
11
12
import 'package:flutter/material.dart';

class AppInfoProvider with ChangeNotifier {
String _themeColor = '';

String get themeColor => _themeColor;

setTheme(String themeColor) {
_themeColor = themeColor;
notifyListeners();
}
}

在main.dart中设置全局数据的主题样式。有多个状态管理就使用MultiProvider,单个的使用Provider.value就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class MyApp extends StatelessWidget {

@override
Widget build(BuildContext context) {

final router = Router();
Routers.configureRouters(router);
Application.router = router;
Color _themeColor;

return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: AppInfoProvider())
],
child: Consumer<AppInfoProvider>(
builder: (context, appInfo, _) {
String colorKey = appInfo.themeColor;
if (themeColorMap[colorKey] != null) {
_themeColor = themeColorMap[colorKey];
}

return MaterialApp(
onGenerateRoute: Application.router.generator,
theme: ThemeData.light().copyWith(
primaryColor: _themeColor,
accentColor: _themeColor,
indicatorColor: Colors.white
),
home: SplashPage(),
);
},
),
);
}
}

设置全局的主题样式

1
Provider.of<AppInfoProvider>(context).setTheme(colorKey);

使用shared_preferences持久化

编写工具类,把shared_preferences做成全局单例模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import 'dart:convert';
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:synchronized/synchronized.dart';

class SpHelper {
static SpHelper _intance;
static SharedPreferences _prefs;
static Lock _lock = Lock();

static Future<SpHelper> getInstance() async {
if (_intance == null) {
await _lock.synchronized(() async {
if (_intance == null) {
// 保持本地实例直到完全初始化。
var instance = SpHelper._();
await instance._init();
_intance = instance;
}
});
}
return _intance;
}

// 私有构造函数
SpHelper._();

Future _init() async {
_prefs = await SharedPreferences.getInstance();
}

/// put object.
static Future<bool> putObject(String key, Object value) {
if (_prefs == null) return null;
return _prefs.setString(key, value == null ? "" : json.encode(value));
}

/// get obj.
static T getObj<T>(String key, T f(Map v), {T defValue}) {
Map map = getObject(key);
return map == null ? defValue : f(map);
}

/// get object.
static Map getObject(String key) {
if (_prefs == null) return null;
String _data = _prefs.getString(key);
return (_data == null || _data.isEmpty) ? null : json.decode(_data);
}

/// put object list.
static Future<bool> putObjectList(String key, List<Object> list) {
if (_prefs == null) return null;
List<String> _dataList = list?.map((value) {
return json.encode(value);
})?.toList();
return _prefs.setStringList(key, _dataList);
}

/// get obj list.
static List<T> getObjList<T>(String key, T f(Map v),
{List<T> defValue = const []}) {
List<Map> dataList = getObjectList(key);
List<T> list = dataList?.map((value) {
return f(value);
})?.toList();
return list ?? defValue;
}

/// get object list.
static List<Map> getObjectList(String key) {
if (_prefs == null) return null;
List<String> dataLis = _prefs.getStringList(key);
return dataLis?.map((value) {
Map _dataMap = json.decode(value);
return _dataMap;
})?.toList();
}

/// get string.
static String getString(String key, {String defValue = ''}) {
if (_prefs == null) return defValue;
return _prefs.getString(key) ?? defValue;
}

/// put string.
static Future<bool> putString(String key, String value) {
if (_prefs == null) return null;
return _prefs.setString(key, value);
}

/// get bool.
static bool getBool(String key, {bool defValue = false}) {
if (_prefs == null) return defValue;
return _prefs.getBool(key) ?? defValue;
}

/// put bool.
static Future<bool> putBool(String key, bool value) {
if (_prefs == null) return null;
return _prefs.setBool(key, value);
}

/// get int.
static int getInt(String key, {int defValue = 0}) {
if (_prefs == null) return defValue;
return _prefs.getInt(key) ?? defValue;
}

/// put int.
static Future<bool> putInt(String key, int value) {
if (_prefs == null) return null;
return _prefs.setInt(key, value);
}

/// get double.
static double getDouble(String key, {double defValue = 0.0}) {
if (_prefs == null) return defValue;
return _prefs.getDouble(key) ?? defValue;
}

/// put double.
static Future<bool> putDouble(String key, double value) {
if (_prefs == null) return null;
return _prefs.setDouble(key, value);
}

/// get string list.
static List<String> getStringList(String key,
{List<String> defValue = const []}) {
if (_prefs == null) return defValue;
return _prefs.getStringList(key) ?? defValue;
}

/// put string list.
static Future<bool> putStringList(String key, List<String> value) {
if (_prefs == null) return null;
return _prefs.setStringList(key, value);
}

/// get dynamic.
static dynamic getDynamic(String key, {Object defValue}) {
if (_prefs == null) return defValue;
return _prefs.get(key) ?? defValue;
}

/// have key.
static bool haveKey(String key) {
if (_prefs == null) return null;
return _prefs.getKeys().contains(key);
}

/// get keys.
static Set<String> getKeys() {
if (_prefs == null) return null;
return _prefs.getKeys();
}

/// remove.
static Future<bool> remove(String key) {
if (_prefs == null) return null;
return _prefs.remove(key);
}

/// clear.
static Future<bool> clear() {
if (_prefs == null) return null;
return _prefs.clear();
}

///Sp is initialized.
static bool isInitialized() {
return _prefs != null;
}
}

页面初始化加载时,从shared_preferences获取主题样式。一般写在main.dart或者闪屏页面

1
2
3
4
5
6
7
8
9
10
11
12
@override
void initState() {
super.initState();
_initAsync();
}

void _initAsync() async {
await SpHelper.getInstance();
String colorKey = SpHelper.getString(Constant.key_theme_color, defValue: 'blue');
// 设置初始化主题颜色
Provider.of<AppInfoProvider>(context).setTheme(colorKey);
}

设置主题样式

1
2
3
4
5
setState(() {
_colorKey = key;
});
SpHelper.putString(Constant.key_theme_color, key);
Provider.of<AppInfoProvider>(context).setTheme(key);

相关的其他代码

设置页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import 'package:flutter/material.dart';
import 'package:music_app/common/sp_helper.dart';
import 'package:music_app/router/application.dart';
import 'package:music_app/common/common.dart';
import 'package:provider/provider.dart';
import 'package:music_app/provider/app_info.dart';

class SettingPage extends StatefulWidget {
@override
_SettingPageState createState() => _SettingPageState();
}

class _SettingPageState extends State<SettingPage> {

String _colorKey;

@override
void initState() {
super.initState();

_initAsync();
}

_initAsync() async {
setState(() {
_colorKey = SpHelper.getString(Constant.key_theme_color, defValue: 'blue');
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Application.router.pop(context);
},
),
title: Text('设置'),
centerTitle: true,
),
body: ListView(
children: <Widget>[
ExpansionTile(
leading: Icon(Icons.color_lens),
title: Text('主题'),
initiallyExpanded: true,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
child: Wrap(
spacing: 8,
runSpacing: 8,
children: themeColorMap.keys.map((key) {
Color value = themeColorMap[key];
return InkWell(
onTap: () {
setState(() {
_colorKey = key;
});
SpHelper.putString(Constant.key_theme_color, key);
Provider.of<AppInfoProvider>(context).setTheme(key);
},
child: Container(
width: 40,
height: 40,
color: value,
child: _colorKey == key ? Icon(Icons.done, color: Colors.white,) : null,
),
);
}).toList(),
),
)
],
),
ListTile(
leading: Icon(Icons.language),
title: Text('多语言'),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('跟随系统', style: TextStyle(
fontSize: 14.0,
color: Colors.grey,
)),
Icon(Icons.keyboard_arrow_right)
],
),
)
],
),
);
}
}

坚持原创技术分享,您的支持将鼓励我继续创作!