feat: 主题切换

This commit is contained in:
guozhigq
2023-08-11 16:35:07 +08:00
parent f4dc4be811
commit c55887af53
6 changed files with 155 additions and 24 deletions

View File

@ -4,8 +4,10 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/common/widgets/custom_toast.dart';
import 'package:pilipala/http/init.dart';
import 'package:pilipala/models/common/theme_type.dart';
import 'package:pilipala/pages/search/index.dart';
import 'package:pilipala/pages/video/detail/index.dart';
import 'package:pilipala/router/app_pages.dart';
@ -33,19 +35,38 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
Color brandColor = Colors.green;
Box setting = GStrorage.setting;
ThemeType currentThemeValue = ThemeType.values[setting
.get(SettingBoxKey.themeMode, defaultValue: ThemeType.system.code)];
return DynamicColorBuilder(
builder: ((lightDynamic, darkDynamic) {
builder: ((ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
ColorScheme? lightColorScheme;
ColorScheme? darkColorScheme;
if (lightDynamic != null && darkDynamic != null) {
// dynamic取色成功
lightColorScheme = lightDynamic.harmonized();
darkColorScheme = darkDynamic.harmonized();
} else {
// dynamic取色失败采用品牌色
lightColorScheme = ColorScheme.fromSeed(
seedColor: brandColor,
brightness: Brightness.light,
);
darkColorScheme = ColorScheme.fromSeed(
seedColor: brandColor,
brightness: Brightness.dark,
);
}
// 图片缓存
// PaintingBinding.instance.imageCache.maximumSizeBytes = 1000 << 20;
return GetMaterialApp(
title: 'PiLiPaLa',
theme: ThemeData(
// fontFamily: 'HarmonyOS',
colorScheme: lightDynamic ??
ColorScheme.fromSeed(
seedColor: Colors.green,
brightness: Brightness.light,
),
colorScheme: currentThemeValue == ThemeType.dark
? darkColorScheme
: lightColorScheme,
useMaterial3: true,
pageTransitionsTheme: const PageTransitionsTheme(
builders: <TargetPlatform, PageTransitionsBuilder>{
@ -57,11 +78,9 @@ class MyApp extends StatelessWidget {
),
darkTheme: ThemeData(
// fontFamily: 'HarmonyOS',
colorScheme: darkDynamic ??
ColorScheme.fromSeed(
seedColor: Colors.green,
brightness: Brightness.dark,
),
colorScheme: currentThemeValue == ThemeType.light
? lightColorScheme
: darkColorScheme,
useMaterial3: true,
),
localizationsDelegates: const [

View File

@ -0,0 +1,13 @@
enum ThemeType {
light,
dark,
system,
}
extension ThemeTypeDesc on ThemeType {
String get description => ['浅色', '深色', '跟随系统'][index];
}
extension ThemeTypeCode on ThemeType {
int get code => [0, 1, 2][index];
}

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/models/common/theme_type.dart';
import 'package:pilipala/models/user/info.dart';
import 'package:pilipala/models/user/stat.dart';
import 'package:pilipala/utils/storage.dart';
@ -10,9 +12,11 @@ class MineController extends GetxController {
Rx<UserInfoData> userInfo = UserInfoData().obs;
// 用户状态 动态、关注、粉丝
Rx<UserStat> userStat = UserStat().obs;
Box user = GStrorage.user;
RxBool userLogin = false.obs;
Box user = GStrorage.user;
Box setting = GStrorage.setting;
Box userInfoCache = GStrorage.userInfo;
Rx<ThemeType> themeType = ThemeType.system.obs;
@override
onInit() {
@ -21,6 +25,9 @@ class MineController extends GetxController {
if (userInfoCache.get('userInfoCache') != null) {
userInfo.value = userInfoCache.get('userInfoCache');
}
themeType.value = ThemeType.values[setting.get(SettingBoxKey.themeMode,
defaultValue: ThemeType.system.code)];
}
onLogin() async {
@ -90,4 +97,31 @@ class MineController extends GetxController {
userLogin.value = false;
// Get.find<MainController>().resetLast();
}
onChangeTheme() {
Brightness currentBrightness =
MediaQuery.of(Get.context!).platformBrightness;
ThemeType currentTheme = themeType.value;
switch (currentTheme) {
case ThemeType.dark:
setting.put(SettingBoxKey.themeMode, ThemeType.light.code);
themeType.value = ThemeType.light;
break;
case ThemeType.light:
setting.put(SettingBoxKey.themeMode, ThemeType.dark.code);
themeType.value = ThemeType.dark;
break;
case ThemeType.system:
// 判断当前的颜色模式
if (currentBrightness == Brightness.light) {
setting.put(SettingBoxKey.themeMode, ThemeType.dark.code);
themeType.value = ThemeType.dark;
} else {
setting.put(SettingBoxKey.themeMode, ThemeType.light.code);
themeType.value = ThemeType.light;
}
break;
}
Get.forceAppUpdate();
}
}

View File

@ -5,6 +5,8 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/models/common/theme_type.dart';
import 'package:pilipala/utils/storage.dart';
import 'controller.dart';
class MinePage extends StatelessWidget {
@ -24,13 +26,11 @@ class MinePage extends StatelessWidget {
title: null,
actions: [
IconButton(
onPressed: () {
Get.changeThemeMode(ThemeMode.dark);
},
onPressed: () => mineController.onChangeTheme(),
icon: Icon(
Get.theme == ThemeData.light()
? CupertinoIcons.moon
: CupertinoIcons.sun_max,
mineController.themeType.value == ThemeType.dark
? CupertinoIcons.sun_max
: CupertinoIcons.moon,
size: 22,
),
),
@ -93,7 +93,7 @@ class MinePage extends StatelessWidget {
src: _mineController.userInfo.value.face,
width: 85,
height: 85)
: Image.asset('assets/images/loading.png'),
: Image.asset('assets/images/noface.jpeg'),
),
),
),

View File

@ -1,11 +1,9 @@
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/http/init.dart';
import 'package:pilipala/pages/dynamics/index.dart';
import 'package:pilipala/models/common/theme_type.dart';
import 'package:pilipala/pages/home/index.dart';
import 'package:pilipala/pages/main/index.dart';
import 'package:pilipala/pages/mine/controller.dart';
import 'package:pilipala/utils/data.dart';
import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/storage.dart';
@ -17,6 +15,7 @@ class SettingController extends GetxController {
RxBool userLogin = false.obs;
RxBool feedBackEnable = false.obs;
RxInt picQuality = 10.obs;
Rx<ThemeType> themeType = ThemeType.system.obs;
@override
void onInit() {
@ -26,6 +25,8 @@ class SettingController extends GetxController {
setting.get(SettingBoxKey.feedBackEnable, defaultValue: false);
picQuality.value =
setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10);
themeType.value = ThemeType.values[setting.get(SettingBoxKey.themeMode,
defaultValue: ThemeType.system.code)];
}
loginOut() async {

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/models/common/theme_type.dart';
import 'package:pilipala/utils/storage.dart';
import 'controller.dart';
@ -16,11 +17,13 @@ class _StyleSettingState extends State<StyleSetting> {
final SettingController settingController = Get.put(SettingController());
Box setting = GStrorage.setting;
late int picQuality;
late ThemeType _tempThemeValue;
@override
void initState() {
super.initState();
picQuality = setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10);
_tempThemeValue = settingController.themeType.value;
}
@override
@ -74,7 +77,7 @@ class _StyleSettingState extends State<StyleSetting> {
final SettingController settingController =
Get.put(SettingController());
return AlertDialog(
title: Text('图片清晰度 - $picQuality%', style: titleStyle),
title: const Text('图片质量'),
contentPadding: const EdgeInsets.only(
top: 20, left: 8, right: 8, bottom: 8),
content: SizedBox(
@ -94,7 +97,11 @@ class _StyleSettingState extends State<StyleSetting> {
actions: [
TextButton(
onPressed: () => Get.back(),
child: const Text('取消')),
child: Text('取消',
style: TextStyle(
color: Theme.of(context)
.colorScheme
.outline))),
TextButton(
onPressed: () {
setting.put(
@ -120,6 +127,63 @@ class _StyleSettingState extends State<StyleSetting> {
),
),
),
ListTile(
dense: false,
onTap: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('主题模式'),
contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12),
content: StatefulBuilder(
builder: (context, StateSetter setState) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
for (var i in ThemeType.values) ...[
RadioListTile(
value: i,
title: Text(i.description, style: titleStyle),
groupValue: _tempThemeValue,
onChanged: (ThemeType? value) {
setState(() {
_tempThemeValue = i;
});
},
),
]
],
);
}),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(
'取消',
style: TextStyle(
color: Theme.of(context).colorScheme.outline),
)),
TextButton(
onPressed: () {
settingController.themeType.value = _tempThemeValue;
setting.put(
SettingBoxKey.themeMode, _tempThemeValue.code);
Get.forceAppUpdate();
Get.back();
},
child: const Text('确定'))
],
);
},
);
},
title: Text('主题模式', style: titleStyle),
subtitle: Obx(() => Text(
'当前模式:${settingController.themeType.value.description}',
style: subTitleStyle)),
trailing: const Icon(Icons.arrow_right_alt_outlined),
),
],
),
);