本文已参与「新人创作礼」活动,一起开启掘金创作之路
基于GetX 搭建通用flutter 项目《二》(界面规范抽象类)
基于GetX 搭建通用flutter 项目《五》(基于GetX 进行动态刷新)
加快脚步,马不停歇,趁这几天事情不多,赶快把之前欠的东西补上。好了,废话不多说了,上“技师”
-
DEMO更新日志
2022-07-14 完成国际化 2022-06-22 完成暗黑模式功能开发 2022-06-16 完成项目基础架构
您能在这里看到啥
- 运行效果
- 暗黑模式
- 跟随系统
- 主题配置
- 项目地址 相对基于GetX 搭建通用flutter 项目《二》(界面规范抽象类)这篇文章来说,暗黑模式和基于GetX 搭建通用flutter 项目《四》(国际化)相对来说简单了许多,最多的就是,需要你有耐心,把所需要的主题和语言配置好就行了
运行效果
暗黑模式
这里我就不再介绍啥是暗黑模式了,咱们直接上代码,因为代码最直观.
主题切换
主题配置主要分为三步 第一步就是👆我们配置主题配置项,不管是用第一种,还是第二种,都是要把对应的主题颜色进行配置 第二步就是在入口页MaterialApp进行主题的设置. 第三步就是在切换主题事件中,进行主题切换,以及状态更新
1.配置主题
下面是我项目中配置的颜色主题。 我在这里也定义了一个主题颜色的抽象类
abstract class AbsThemeColorConfig {
/// 这里配置正常颜色
Map<String, Color?> lightInfo = {};
/// 这里配置暗黑颜色
Map<String, Color?> darkInfo = {};
/// 获取配置当前颜色
Color confgColor(String colkey, {bool reversal = false}) {
bool isbackmodel = loadThemeModel();
if (reversal) {
isbackmodel = !isbackmodel;
}
Map colorinfo = isbackmodel ? darkInfo : lightInfo;
return colorinfo[colkey] ?? Colors.black;
}
/// 获取当前的主题模式 使用者可以重写这个方法,来改变当前的主题状态
bool loadThemeModel() {
return false;
}
}
👇是我项目里使用的情况
/// 这是我定义的颜色key
class HzyColorSring {
static String coltheme = "theme";
static String colffffff = "ffffff";
static String col000000 = "000000";
static String whitebgblacktextcolor = "whiteback";
}
class HzyThemeColor extends AbsThemeColorConfig {
/// 这是个单利
HzyThemeColor._internal();
factory HzyThemeColor() => _instance;
static late final HzyThemeColor _instance = HzyThemeColor._internal();
@override
Map<String, Color?> get lightInfo =>
HzyColorSring.coltheme: CommentColorS.col2865ff,
HzyColorSring.colffffff: CommentColorS.colffffff,
HzyColorSring.col000000: CommentColorS.col000000,
};
@override
Map<String, Color?> get darkInfo => {
HzyColorSring.coltheme: CommentColorS.col2865ff,
HzyColorSring.colffffff: CommentColorS.col171717,
HzyColorSring.col000000: CommentColorS.colffffff,
};
@override
bool loadThemeModel() {
/// 这里里面是我获取 主题的方法来我们看看一下里面实现的内容
return ThemeTool.isdark();
}
}
现在开始讲一下 具体的主题改变的状态监听
static isdark() {
/// 这是本地存的 主题的状态,因为需要持有化,所以会把对应的状态,存起来
/// 深色模式 0: 关闭 1: 开启 2: 随系统
int type = CommonSpUtil.getThemeType();
if (type == 2) {
/// 这里是 跟随系统的逻辑,判断当前状态,来返回对应的主题
return MediaQuery.of(Get.context!).platformBrightness == Brightness.dark;
} else {
return Get.isDarkMode;
}
}
为了使用方便,我又把上面的做了一下封装,具体你们封不封装 取决于习惯,下面是我封装的类
class HzyColorConfig {
Color colthemes = HzyThemeColor().confgColor(HzyColorSring.coltheme);
Color col000000 = HzyThemeColor().confgColor(HzyColorSring.col000000);
}
到此,其实颜色的配置已经完成,具体您的项目,可能会有很多颜色值的配置,那就是重复的东西了,费点时间就可以下了. 当然你也可以用系统自带的Theme* 来做处理,👇我也简单的举个🌰.
//创建Dark ThemeData对象
final ThemeData appDarkThemeData = ThemeData(
brightness: Brightness.dark,
primaryColor: CommentColorS.col010101,
splashColor: Colors.white.withOpacity(0),
splashFactory: const NormalNoSplashFactory(),
highlightColor: Colors.white.withOpacity(0),
scaffoldBackgroundColor:CommentColorS.col010101,
textTheme: const TextTheme(
headline5: TextStyle(
color: CommentColorS.colffffff,
fontWeight: FontWeight.bold,
fontSize: 24),
bodyText1: TextStyle(
color: CommentColorS.colffffff,
fontSize: 16.0,
),
bodyText2: TextStyle(
color: CommentColorS.colffffff,
fontSize: 14,
),
),
appBarTheme: const AppBarTheme(
iconTheme: IconThemeData(color: Colors.white),
backgroundColor: CommentColorS.col010101,
),
);
//创建light ThemeData对象
final ThemeData appLightThemeData = ThemeData(
brightness: Brightness.light,
primaryColor: CommentColorS.colffffff,
splashColor: Colors.white.withOpacity(0),
highlightColor: Colors.white.withOpacity(0),
splashFactory: const NormalNoSplashFactory(),
scaffoldBackgroundColor:
CommentColorS.colffffff,
textTheme: const TextTheme(
/// 字体24
headline5: TextStyle(
color: CommentColorS.col333333,
fontWeight: FontWeight.bold,
),
bodyText1: TextStyle(
color: CommentColorS.col333333,
fontSize: 16.0,
),
bodyText2:
TextStyle(color: CommentColorS.col333333, fontSize: 14)), // 字体主题
appBarTheme: const AppBarTheme(
iconTheme: IconThemeData(color: Colors.black),
backgroundColor: Colors.white,
),
);
2.MaterialApp
👇是我代码中MaterialApp配置清单
class Application extends StatelessWidget {
Application({Key? key}) : super(key: key);
final easyLoading = EasyLoading.init();
@override
Widget build(BuildContext context) {
String rootroutes = UtilsTool.configrootpageid();
return ScreenUtilInit(
designSize: const Size(375, 667),
minTextAdapt: true,
splitScreenMode: true,
builder: (_) {
return GestureDetector(
/// 全局点击 事件
onTap: () => CommentTools.keydissmiss(context),
/// 通过GetX 创建根视图
child: GetMaterialApp(
// /// 入口路由
initialRoute: rootroutes,
/// 所有路由集合
getPages: RouterS.getAllRoutS(),
/// 是否显示 导航栏右上角 debug 标识
debugShowCheckedModeBanner: false,
builder: (context, child) => MediaQuery(
//设置文字大小不随系统设置改变
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: easyLoading(context, child),
),
/// 这里如果你使用ThemeData 可以在这里使用你定义的themeData
theme: ThemeData(brightness: Brightness.light),
darkTheme: ThemeData(brightness: Brightness.dark),
/// 配置 本地存储 主题类型
themeMode: ThemeTool.getlocalprofileaboutThemeModel(),
/// 国际化配置 代理
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, // ios
],
initialBinding: AllControllerBinding(),
/// 本地支持语言
supportedLocales: const [
Locale('zh', 'CN'),
Locale('en', 'US'),
],
);
);
},
);
}
}
这里面相对关键就是下面这个方法,是为了配置APP启动的时候,配置当前的主题模式.
/// 配置 本地存储 主题类型
themeMode: ThemeTool.getlocalprofileaboutThemeModel(),
我们来看一下这个getlocalprofileaboutThemeModel()方法里是怎么实现呢
/// 获取本地 主题配置
static getlocalprofileaboutThemeModel() {
int theme = CommonSpUtil.getThemeType();
ThemeMode themeMode = ThemeMode.light;
if (theme == 0) {
/// 正常模式
themeMode = ThemeMode.light;
} else if (theme == 1) {
/// 暗黑模式
themeMode = ThemeMode.dark;
} else if (theme == 2) {
/// 跟随系统模式
themeMode = ThemeMode.system;
}
return themeMode;
}
3.切换主题
前面两步配置好了,下面就是我们来使用切换主题的事情了,具体页面样式,是你们自己的,我这边是模仿微信写的,来,我们看看具体的切换事件是怎么实现的
/// 切换主题
static changeTheme({int? type = 1}) {
/// 获取当前的主题模型
ThemeMode mode = getlocalprofileaboutThemeModel();
/// 配置当前的主题数据
ThemeData themeData = getlocalprofileaboutThemeData();
/// 由于我这里使用第三方加载动画,也把这个进行了状态的修改
EasyLoadingStyle easyLoadingStyle = EasyLoadingStyle.dark;
if (mode == ThemeMode.dark) {
easyLoadingStyle = EasyLoadingStyle.light;
} else if (mode == ThemeMode.system) {
if (!Get.isDarkMode) {
easyLoadingStyle = EasyLoadingStyle.light;
}
}
EasyLoading.instance.loadingStyle = easyLoadingStyle;
/// 然后使用GetX 提供的切换方式,进行动态更新就可以
Get.changeThemeMode(mode);
Get.changeTheme(themeData);
/// 这个比较重要,如果不使用这个,可能会导致主题没有及时更新
updateTheme();
}
/// 更新主题
static updateTheme() {
Future.delayed(const Duration(milliseconds: 250), () {
Get.forceAppUpdate();
});
}
/// 根据本地存储的状态,进行主题数据赋值
static getlocalprofileaboutThemeData() {
int theme = CommonSpUtil.getThemeType();
ThemeData themeData = ThemeData.light();
if (theme == 0) {
themeData = ThemeData(brightness: Brightness.light);
} else if (theme == 1) {
themeData = ThemeData(brightness: Brightness.dark);
} else if (theme == 2) {
if (!Get.isDarkMode) {
themeData = ThemeData(brightness: Brightness.dark);
} else {
themeData = ThemeData(brightness: Brightness.light);
}
}
return themeData;
}
到此主题切换就完成,好像本地存储没有讲,但是这个相对来说简单点,你可以自行看项目
好了分享结束,马上开始写第四篇文章 基于GetX 搭建通用flutter 项目《四》(国际化)
喜欢的可以点点赞,你们的鼓励,就是我前进的动力.谢谢
hzy_normal_widget 是我在使用GetX搭建项目时,总结的一些通用开发控件,方便我们在开发的时候,减少重复性界面代码的创建.
ttcomment 通用项目的界面接口基类,和一些通用工具类,喜欢的可以点点star.
当然接下的时间里我也会总结OC 和 swift 相应的通用项目文章,喜欢的可以点点关注