觉得有帮助的可以点个赞喔😯
代码
效果
导航
- Flutter学习篇(一)—— Dialog的简单使用
- Flutter学习篇(二)—— Drawer和水纹按压效果
- Flutter学习篇(三)—— MobX的使用和原理
- Flutter学习篇(四)—— 尺寸解惑
- Flutter学习篇(五)——路由剖析前篇
- Flutter学习篇(六)——路由剖析终篇
- Flutter学习篇(七)—— flutter web ➡ 几分钟打造个人网站
前言
随着 iOS13 开始推广黑夜模式,现在各个厂商的 App 也开始着力 App 黑夜模式的改造与实现,而 Flutter 作为新一代的跨平台框架,天然支持了黑夜模式的特性。
介绍
Flutter 内嵌了一套主题常量,可以方便快速地定义整个 App 的样式,如下:
appBar,scaffoldBackgroundColor等,
所以,我们可以通过设置主题的颜色,字体等样式,勾勒出 App 的整体风格,而这个特性就是我们实现黑夜模式的基础。
基础
Flutter 的根 widget MaterialApp有几个关键的属性 —— themeMode, theme,darkTheme,分别对应主题的模式,白天主题,黑夜主题。
themeMode的类型如下:
- system 随着系统设置
- light 白天模式,使用
theme主题 - dark 黑夜模式,使用
darkTheme主题
控制黑白模式的开关就是themeMode,所以如上所说,我们需要在MaterialApp定义好主题:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => GlobalModel()),
],
child: Consumer<GlobalModel>(
builder: (context, globalModel, _) {
GlobalTheme.setDark(globalModel.isDarkTheme);
return MaterialApp(
title: 'Flutter 2020',
debugShowCheckedModeBanner: false,
themeMode: globalModel.isDarkTheme ? ThemeMode.dark : ThemeMode
.light,
theme: GlobalTheme.lightThemeData,
darkTheme: GlobalTheme.darkThemeData,
home: MyHomePage()
);
}
),
);
}
}
theme 的定义如下:
// 生成主题的配色
static genThemeData(bool isDark) {
final theme = isDark ? GlobalTheme.dark : GlobalTheme.light;
return ThemeData(
scaffoldBackgroundColor: theme.appBgColor,
appBarTheme: AppBarTheme(
// 状态栏字体图标颜色
brightness: isDark ? Brightness.dark : Brightness.light,
color: theme.mainBgColor,
iconTheme: IconThemeData(color: theme.appBarFontColor, size: 12),
textTheme: TextTheme(
title: TextStyle(color: theme.appBarFontColor, fontSize: 17)),
));
}
我这里设置了背景颜色,appBar 的主题,通过这样集成,就已经实现了一个简易版的黑白模式。
深入
- 眼尖的读者应该发现我上面使用了provider, 我定义了一个全局的 model,管理黑白模式的开关
// 全局数据管理
class GlobalModel with ChangeNotifier {
bool _isDarkTheme = false;
bool get isDarkTheme => _isDarkTheme;
void switchTheme() {
_isDarkTheme = !_isDarkTheme;
notifyListeners();
}
}
MaterialApp 通过监听这个全局 model,进而切换主题。
- 对于 themeData 没有支持的样式,提供了主题配色设置的能力
mixin ThemeColorConfig {
final Map<String, ColorSelector> _colorSelectorMap = Map();
addColor(String colorKey, {@required Color light, @required Color dark}) {
_colorSelectorMap[colorKey] = ColorSelector(light, dark);
}
getColor(String colorKey) {
assert( _colorSelectorMap[colorKey] != null, "$colorKey对应的颜色值未配置");
return _colorSelectorMap[colorKey].color;
}
@protected
// 主题颜色设置
themeColorsConfig() => {};
}
只要基础页面混合`ThemeColorConfig`, 然后配置好颜色
```dart
themeColorsConfig() {
addColor("darkFont", light: Color(0X4D000000), dark: Color(0X4DFFFFFF));
addColor("lightFont", light: Color(0XFFFFFFFF), dark: Color(0XFFFFFFFF));
}
就可以通过getColor("darkFont")取出当前主题的颜色。
注意点
- q: 状态栏沉浸式的实现?
a: 整理方案如下:// 状态栏背景设置为透明 SystemChrome.setSystemUIOverlayStyle( SystemUiOverlayStyle(statusBarColor: Colors.transparent)); //brightness属性改变状态栏字体图标颜色 //color属性为状态栏颜色 AppBar( color: theme.mainBgColor, brightness: isDark ? Brightness.dark : Brightness.light)
觉得有帮助的可以点个赞喔😯
总结
Flutter天然支持主题的切换,但是这更依赖团队的开发风格,如果在项目前期对于颜色值等样式的使用有明确的规范和标准,能够抽离出一套主题样式,那么接入主题的切换,也就是水到渠成的事情。