参考文章:
https://www.jianshu.com/p/76539f98b146
https://www.jianshu.com/p/7b253699dbc5
1、查看当前的黑暗模式状态
final Brightness brightnessValue = MediaQuery.of(context).platformBrightness;
bool isDark = brightnessValue == Brightness.dark;
代码如下:
dark_mode.dart
/// 深色模式
class DarkMode {
// 判断当前是否为深色模式 true:深色 false:浅色
static bool isDark({BuildContext context}) {
// return false - 完全屏蔽深色模式功能,不开启深色模式
return false;
// if (getDarkModeStatus() == DarkModeStatus.dark) {
// // 深色
//// LogUtils.d('模式', '深色');
// return true;
// } else if (getDarkModeStatus() == DarkModeStatus.light) {
// // 浅色
//// LogUtils.d('模式', '浅色');
// return false;
// } else {
// // 跟随系统
//// LogUtils.d('模式', '跟随系统');
// if (context != null) {
// return MediaQuery.of(context).platformBrightness == Brightness.dark;
// } else {
// return WidgetsBinding.instance.window.platformBrightness == Brightness.dark;
// }
// }
}
// 获取深色模式状态
static DarkModeStatus getDarkModeStatus() {
int status = App.getInstance().getInt(SPKeyConst.darkModeKey);
if (status == null) {
App.getInstance().setInt(SPKeyConst.darkModeKey, 0);
}
if (status == 1) {
return DarkModeStatus.dark;
} else if (status == 2) {
return DarkModeStatus.light;
} else {
return DarkModeStatus.followSystem;
}
}
}
dark_mode_provider.dart
class DarkModeProvider extends ChangeNotifier {
// 同步深色模式
void syncTheme() {
int theme = App.getInstance().getInt(SPKeyConst.darkModeKey);
if (theme != null && theme != 0) {
notifyListeners();
}
}
// 设置深色模式
void setTheme(DarkModeStatus status) {
if (status == DarkModeStatus.followSystem) {
// 设置-跟随系统
App.getInstance().setInt(SPKeyConst.darkModeKey, 0);
} else if (status == DarkModeStatus.dark) {
// 设置深色
App.getInstance().setInt(SPKeyConst.darkModeKey, 1);
} else if (status == DarkModeStatus.light) {
// 设置浅色
App.getInstance().setInt(SPKeyConst.darkModeKey, 2);
}
notifyListeners();
}
// 主题样式
ThemeData getTheme({bool isDark = false}) {
int theme = App.getInstance().getInt(SPKeyConst.darkModeKey);
if (theme == null) {
theme = 0;
}
String themeStr = theme.toString();
switch (themeStr) {
case "1":
isDark = true;
break;
case "2":
isDark = false;
break;
default:
break;
}
return ThemeData(
// 深色/浅色
brightness: isDark ? Brightness.dark : Brightness.light,
// 主题色
primarySwatch: Colors.blue,
// 页面背景色
scaffoldBackgroundColor: isDark ? R.dark_scaffold_bg_color : R.color_white_F6F6F6,
// 背景色
backgroundColor: isDark ? R.dark_scaffold_bg_color : R.color_white,
// 主要用于Material背景色
canvasColor: isDark ? R.dark_bg_color : R.color_white,
// Tab指示器颜色
indicatorColor: isDark ? R.color_green_3CB71D : R.color_green_3CB71D,
// 导航栏默认样式
appBarTheme: AppBarTheme(
elevation: 0,
color: isDark ? R.dark_nav_bg_color : R.color_white,
brightness: isDark ? Brightness.dark : Brightness.light,
textTheme: TextTheme(
headline6: TextStyle(
fontSize: R.font_36,
fontWeight: FontWeight.w500,
color: isDark ? R.color_white : R.color_black_333333,
),
),
),
// 文本样式
textTheme: TextTheme(
// text默认文字样式
bodyText2: TextStyle(
color: isDark ? R.color_white : R.color_black_333333,
),
// TextField输入文字颜色
subtitle1: TextStyle(
color: isDark ? R.color_white : R.color_black_333333,
),
// 小文字样式
subtitle2: TextStyle(
color: isDark ? R.dark_subtitle : R.color_grey_666666,
),
// 说明描述
caption: TextStyle(
color: isDark ? R.dark_caption : R.color_grey_999999,
)),
// 分割线样式
dividerTheme: DividerThemeData(
color: isDark ? R.dark_line : R.color_grey_EEE,
space: 0.6,
thickness: 0.6,
),
);
}
/// 项目通用适配样式 ============================================
// 页面背景色: R.color_white_F6F6F6 / R.dark_scaffold_bg_color
static Color scaffoldBackgroundColor(BuildContext context) {
return Theme.of(context).scaffoldBackgroundColor;
}
// widget背景色: R.color_white / R.dark_bg_color
static Color canvasColor(BuildContext context) {
return Theme.of(context).canvasColor;
}
// 默认文本颜色: R.color_black_333333 / R.color_white
static Color textColor(BuildContext context) {
return Theme.of(context).textTheme.headline6.color;
}
// 默认返回按钮背景色: R.color_black_333333 / R.color_white
static Color navBackColor(BuildContext context) {
return Theme.of(context).textTheme.headline6.color;
}
// 默认导航栏文本样式
static appBarTitleStyle(BuildContext context) {
return Theme.of(context).appBarTheme.textTheme.headline6;
}
// 灰色文本颜色 666666
static gray666666TextColor(BuildContext context) {
return Theme.of(context).textTheme.subtitle2.color;
}
// 灰色文本颜色 999999
static gray999999TextColor(BuildContext context) {
return Theme.of(context).textTheme.caption.color;
}
}
main.dart
中main()
里
runApp(ChangeNotifierProvider(
create: (context) => DarkModeProvider(),
child: MyApp(),
));
main.dart
中MyApp
里
class _MyAppState extends State with WidgetsBindingObserver {
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
// 由于SpUtil未初始化,所以MaterialApp获取的为默认主题配置,这里同步一下。
Provider.of(context, listen: false).syncTheme();
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
MyApp
里
// 监听系统显示模式改变
@override
void didChangePlatformBrightness() {
final Brightness brightness = WidgetsBinding.instance.window.platformBrightness;
if (brightness == Brightness.dark) {
LogUtils.d('tag', '当前系统显示模式:深色模式');
} else {
LogUtils.d('tag', '当前系统显示模式:浅色模式');
}
setState(() {});
}
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: providers,
child: Consumer2(
builder: (_, darkModeProvider, settingsProvider, __) {
return PlatformApp(
theme: darkModeProvider.getTheme(),
// 是否开启深色模式
darkTheme: darkModeProvider.getTheme(isDark: DarkMode.isDark()),
...
...
);
},
),
);
}
设置页
// 进入深色模式
void gotoDarkModeSetting() {
NavigatorRoute.push(
context,
DarkModeSettingPage(),
pageName: RouteName.darkModeSettingPageName,
);
}
// 获取状态
String getDarkModeStatus() {
int status = App.getInstance().getInt(SPKeyConst.darkModeKey) ?? 0;
if (status == 1) {
return '深色';
} else if (status == 2) {
return '浅色';
} else {
return '跟随系统';
}
}
深色模式设置页
/// 深色模式
// 深色模式状态
enum DarkModeStatus {
followSystem, // 跟随系统0
dark, // 深色1
light, // 浅色2
}
class DarkModeSettingPage extends StatefulWidget {
@override
_DarkModeSettingPageState createState() => _DarkModeSettingPageState();
}
class _DarkModeSettingPageState extends State {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
// 设置0跟随系统、1深色、2浅色
void setDarkModeAction(BuildContext context, DarkModeStatus status) {
Provider.of(context, listen: false).setTheme(status);
if (status == DarkModeStatus.followSystem) {
// 设置-跟随系统
App.getInstance().setInt(SPKeyConst.darkModeKey, 0);
} else if (status == DarkModeStatus.dark) {
// 设置深色
App.getInstance().setInt(SPKeyConst.darkModeKey, 1);
} else if (status == DarkModeStatus.light) {
// 设置浅色
App.getInstance().setInt(SPKeyConst.darkModeKey, 2);
}
setState(() {});
}
// 获取状态
DarkModeStatus getDarkModeStatus() {
int status = App.getInstance().getInt(SPKeyConst.darkModeKey) ?? 0;
if (status == 1) {
return DarkModeStatus.dark;
} else if (status == 2) {
return DarkModeStatus.light;
} else {
return DarkModeStatus.followSystem;
}
}
@override
Widget build(BuildContext context) {
return PlatformScaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: PlatformAppBar(
preferredSizeWidget: AppBarWidget(
elevation: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: Container(
padding: EdgeInsets.only(right: 20),
color: R.color_transparent,
width: 64.0,
height: 44.0,
child: Image.asset(
'images/base/black_left_back_icon.png',
width: 8.5,
height: 14,
color: DarkModeProvider.navBackColor(context),
),
),
),
Expanded(
child: Center(
child: Text(
'深色模式',
style: DarkModeProvider.appBarTitleStyle(context),
textAlign: TextAlign.center,
),
),
),
SizedBox(
width: 64,
),
],
),
),
),
body: Container(
child: ListView(
children: [
GestureDetector(
onTap: () {
setDarkModeAction(context, DarkModeStatus.followSystem);
},
behavior: HitTestBehavior.opaque,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 15),
color: Theme.of(context).canvasColor,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 100,
padding: EdgeInsets.symmetric(vertical: 13.5),
child: Text(
'跟随系统',
style: TextStyle(
fontSize: R.font_32,
),
),
),
Offstage(
offstage: getDarkModeStatus() != DarkModeStatus.followSystem,
child: Image.asset('images/base/check_mark.png'),
),
],
),
),
),
Divider(
height: 1,
),
GestureDetector(
onTap: () {
// 深色
setDarkModeAction(context, DarkModeStatus.dark);
},
behavior: HitTestBehavior.opaque,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 15),
color: Theme.of(context).canvasColor,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 100,
padding: EdgeInsets.symmetric(vertical: 13.5),
child: Text(
'深色',
style: TextStyle(
fontSize: R.font_32,
),
),
),
Offstage(
offstage: getDarkModeStatus() != DarkModeStatus.dark,
child: Image.asset('images/base/check_mark.png'),
),
],
),
)),
Divider(
height: 1,
),
GestureDetector(
onTap: () {
// 浅色
setDarkModeAction(context, DarkModeStatus.light);
},
behavior: HitTestBehavior.opaque,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 15),
color: Theme.of(context).canvasColor,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 100,
padding: EdgeInsets.symmetric(vertical: 13.5),
child: Text(
'浅色',
style: TextStyle(
fontSize: R.font_32,
),
),
),
Offstage(
offstage: getDarkModeStatus() != DarkModeStatus.light,
child: Image.asset('images/base/check_mark.png'),
),
],
),
),
),
Divider(
// height: 1,
),
],
),
),
);
}
}
适配注意事项:
导航栏返回按钮
image添加color: DarkModeProvider.navBackColor(context)
导航栏背景色
AppBarWidget中的以下3行代码去掉
backgroundColor: R.color_white,
appBarColor: R.color_white,
brightness: Brightness.light,
导航栏的返回按钮 或 导航栏右侧的按钮,添加 color: DarkModeProvider.navBackColor(context)
中间的居中标题样式,style替换为 style: DarkModeProvider.appBarTitleStyle(context)
- 背景色
页面背景色:
PlatformScaffold中的backgroundColor: Colors.white,
或backgroundColor: R.color_white_F6F6F6,
替换为backgroundColor: Theme.of(context).scaffoldBackgroundColor
widget白色背景:
Colors.white
或 R.color_white
替换为 DarkModeProvider.canvasColor(context)
- 文本颜色
黑色文本颜色R.color_black_333333
去掉,文本颜色会自动改变
注意这里导航栏里的Text文本颜色R.color_black_333333在这里不适用,不要去掉,
而是改为DarkModeProvider.textColor(context)
灰色字体颜色
R.color_grey_666666
替换为 DarkModeProvider.gray666666TextColor(context)
R.color_grey_999999
替换为 DarkModeProvider.gray999999TextColor(context)
- 分割线
Divider的color去掉,颜色自动改变