flutter

基于GetX 搭建通用flutter 项目《三》(暗黑模式)

2022-08-01  本文已影响0人  火之夜工作室

基于GetX 搭建通用flutter 项目《一》

基于GetX 搭建通用flutter 项目《二》(界面规范抽象类)

基于GetX 搭建通用flutter 项目《四》(国际化)

基于GetX 搭建通用flutter 项目《五》(基于GetX 进行动态刷新)

加快脚步,马不停歇,趁这几天事情不多,赶快把之前欠的东西补上。好了,废话不多说了,上“技师”

您能在这里看到啥

  1. 运行效果
  2. 暗黑模式
  3. 跟随系统
  4. 主题配置
  5. 项目地址

相对基于GetX 搭建通用flutter 项目《二》(界面规范抽象类)这篇文章来说,暗黑模式和基于GetX 搭建通用flutter 项目《四》(国际化)相对来说简单了许多,最多的就是,需要你有耐心,把所需要的主题和语言配置好就行了

运行效果

1657349104736057.gif

暗黑模式

这里我就不再介绍啥是暗黑模式了,咱们直接上代码,因为代码最直观.

主题切换

主题配置主要分为三步
第一步就是👆我们配置主题配置项,不管是用第一种,还是第二种,都是要把对应的主题颜色进行配置
第二步就是在入口页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.

当然接下的时间里我也会总结OCswift 相应的通用项目文章,喜欢的可以点点关注

上一篇下一篇

猜你喜欢

热点阅读