1.瞎叨叨

也不知道写点什么,本来想写写Flutter的集成测试。因为前一阵子给flutter_deer写了一套,不过感觉也没啥内容,写不了几句话就放弃了。(其实本篇内容也不多。。。)

那就写写最近在做的事情。没错,就是文章标题提到的适配深色模式(DarkMode),也可以说是实现夜间模式的功能。相信许多iOS的同学最近都比较关注,毕竟iOS 13上个月推送更新了。

说适配的原因是因为在iOS 13 和 Android 10系统上它都属于新特性。适配的目的是为了达到应用的主题随着系统主题模式的切换而变化,给用户更好的一致性体验。与它类似的就是系统语言的设置,当系统设置某种语言时,应用内的文字也相应变化。

好在Flutter也提供了适配的入口,使得我们可以一次适配两个平台。我手上的小米mix2s虽然是Android 9 的,没想到也能适配。

2.准备工作

下面我就说说我在适配flutter_deer中的经验,Flutter版本1.9.1。

首先是规范问题,标题、副标题、分割线、各种背景等颜色,以及深色模式下相对应的颜色一定要先规范起来。否则你自己不仅被这些颜色搞得眼冒金星,同时应用也没有一个统一的风格。

3.适配开始

1.全局调整

Flutter 在 MaterialApp中提供了themedarkTheme两个入口让我们设置两种模式下的颜色及文字样式。接收的ThemeData中近乎涵盖了所有Material Widget中所使用的颜色及主题。(Cupertino系列组件官方还在适配中,所以Flutter版本1.9.1暂不支持。)

通过配置themedarkTheme可以让我们省去很多的判断代码,比如我的分割线在不同模式下是两种不同颜色,我不可能每使用一次,就在使用的地方去判断一次。通过配置全局dividerTheme,我们就可以直接使用Divider()或者BorderSide

 ThemeData(dividerTheme: DividerThemeData(color: isDarkMode ? Colours.dark_line : Colours.line,space: 0.6,thickness: 0.6));

同样我们的页面背景色、文字样式都可以这样配置。以下就是deer中最终整理的配置。

 ThemeData(errorColor: isDarkMode ? Colours.dark_red : Colours.red,brightness: isDarkMode ? Brightness.dark : Brightness.light,primaryColor: isDarkMode ? Colours.dark_app_main : Colours.app_main,accentColor: isDarkMode ? Colours.dark_app_main : Colours.app_main,// Tab指示器颜色indicatorColor: isDarkMode ? Colours.dark_app_main : Colours.app_main,// 页面背景色scaffoldBackgroundColor: isDarkMode ? Colours.dark_bg_color : Colors.white,// 主要用于Material背景色canvasColor: isDarkMode ? Colours.dark_material_bg : Colors.white,// 文字选择色(输入框复制粘贴菜单)textSelectionColor: Colours.app_main.withAlpha(70),textSelectionHandleColor: Colours.app_main,textTheme: TextTheme(// TextField输入文字颜色subhead: isDarkMode ? TextStyles.textDark : TextStyles.text,// Text默认文字样式body1: isDarkMode ? TextStyles.textDark : TextStyles.text,// 这里用于小文字样式subtitle: isDarkMode ? TextStyles.textDarkGray12 : TextStyles.textGray12,),inputDecorationTheme: InputDecorationTheme(hintStyle: isDarkMode ? TextStyles.textHint14 : TextStyles.textDarkGray14,),appBarTheme: AppBarTheme(elevation: 0.0,color: isDarkMode ? Colours.dark_bg_color : Colors.white,brightness: isDarkMode ? Brightness.dark : Brightness.light,),dividerTheme: DividerThemeData(color: isDarkMode ? Colours.dark_line : Colours.line,space: 0.6,thickness: 0.6));

使用:

 MaterialApp (title: 'Flutter Deer',theme: getTheme(),darkTheme: getTheme(isDarkMode: true),home: TestPage());

当然有些Widget没有使用到,所以也就没有去适配。以上这些color、theme具体的使用地方需要自己去翻看源码及注释才能知道,所以这是一个比较费力的过程。

其实这里你也可以利用某些“坑位”,比如应用内的另外一种功能文字在字号、颜色上都与主文字不一样,使用的地方还很多,每次使用再判断也很麻烦,这样就可以设置到未使用的属性上,比如上面代码中的subtitle。这样使用时就可以通过调用Theme.of(context).textTheme.subtitle来实现。

Text("文字", style: Theme.of(context).textTheme.subtitle
)

需要注意的是:毕竟是全局配置,尽量保持通用,不要影响其他widget也是要考虑的地方。

这部分配置完成后,你需要的是"去同存异"。

  1. 比如你指定的文字样式与全局配置相同时,就需要删除它。

  2. 如果文字颜色相同,但是字号不同。那就删除颜色配置信息,保留字号设置:

Text("仅保留不同信息",style: const TextStyle(fontSize: 12.0,)
)

因为Text的源码中就是通过merge方法来合并全局配置与局部配置。merge中其实就是调用copyWith来实现的。所以也可以这样写:

Text("仅保留不同信息",style: Theme.of(context).textTheme.body1.copyWith(fontSize: 12.0)
)
  1. 颜色不同。因为深色模式主要就是颜色变化,所以可以考虑上面的“subtitle”方案。如果仅有几处,可以封装一些方法统一判断处理。

2.局部调整

在经过全局的配置后,大多数适配问题得到了解决。但可能还有一些细节要调整,比如图标、个别的文字颜色、背景色。这时需要的就是如何判断深色模式:

  bool isDarkMode(BuildContext context){return Theme.of(context).brightness == Brightness.dark;}

这里的brightness就是上面在全局配置ThemeData中指定的brightness

Tips:

  1. 有些纯色的小图标可以直接使用Image.assetcolor来修改。

  2. ButtontextColor属性最好还是局部处理,因为源码中“非黑即白”,我很痛苦啊!

  /// The foreground color of the [button]'s text and icon.////// If [button] is not [MaterialButton.enabled], the value of/// [getDisabledTextColor] is returned. If the button is enabled and/// [buttonTextColor] is non-null, then [buttonTextColor] is returned.////// Otherwise the text color depends on the value of [getTextTheme]/// and [getBrightness].//////  * [ButtonTextTheme.normal]: [Colors.white] is used if [getBrightness]///    resolves to [Brightness.dark]. [Colors.black87] is used if///    [getBrightness] resolves to [Brightness.light].///  * [ButtonTextTheme.accent]: [colorScheme.secondary].///  * [ButtonTextTheme.primary]: If [getFillColor] is dark then [Colors.white],///    otherwise if [button] is a [FlatButton] or an [OutlineButton] then///    [colorScheme.primary], otherwise [Colors.black].Color getTextColor(MaterialButton button) {if (!button.enabled)return getDisabledTextColor(button);if (button.textColor != null)return button.textColor;switch (getTextTheme(button)) {case ButtonTextTheme.normal:return getBrightness(button) == Brightness.dark ? Colors.white : Colors.black87;case ButtonTextTheme.accent:return colorScheme.secondary;case ButtonTextTheme.primary: {final Color fillColor = getFillColor(button);final bool fillIsDark = fillColor != null? ThemeData.estimateBrightnessForColor(fillColor) == Brightness.dark: getBrightness(button) == Brightness.dark;if (fillIsDark)return Colors.white;if (button is FlatButton || button is OutlineButton)return colorScheme.primary;return Colors.black;}}assert(false);return null;}

2020.01.01 补充:

如果启动页需要适配的话,要考虑应用启动时短暂的白屏现象。(比如启动时白屏,启动页为黑色背景,这样会不和谐)最优的方式是使用Android、iOS原生的方式处理应用启动与启动页的过渡。

这里我介绍一下简易版的方式:

Android端:

android -> app -> src -> main -> res 目录下新建 drawable-night 文件夹,添加launch_background.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item ><color android:color="#FF18191A"/> <-- 具体的颜色色值</item>
</layer-list>

这样在深色模式下,会使用对应的颜色背景。(当然要保证你的默认样式使用到了此文件)

iOS端:

修改BackgroundSystem Background Color

具体的代码示例点击查看

3.功能拓展

如果你适配好了深色模式,其实可以稍微拓展一下这个功能。我想到了微信中的多语言功能,在多语言这类功能中,默认选项是“跟随系统”,当然你也可以指定某种语言。

按照这个思路我在设置中添加了“夜间模式”的功能,默认也是跟随系统,当然你也可以手动的开启和关闭。

这里暂时有个问题,在iOS手机上开启深色模式,当我应用内关闭深色模式后,状态栏文字无法变为黑色。

问题主要还是Flutter 1.9.1的版本并没有适配iOS 13 Status Bar增的UIStatusBarStyleDarkContent

这个问题Flutter的issues中也有人反馈了,期待官方的适配修复吧。

上述这些,基本就是适配深色模式主要内容了。本身没有什么复杂的,主是是个细心活。

说了这么多,最后放几张适配的效果图给大家看看:

详细的代码以及实现细节,可以参看flutter_deer的代码。深色模式相关的设计图也已经同步更新了。最后希望可以点赞支持一波!!!

4.参考

  • iOS13 新特性简介

Flutter适配深色模式(DarkMode)相关推荐

  1. iOS13适配深色模式(Dark Mode)

    原文博客地址: iOS13适配深色模式(Dark Mode) 好像大概也许是一年前, Mac OS系统发布了深色模式外观, 看着挺刺激, 时至今日用着也还挺爽的 终于, 随着iPhone11等新手机的 ...

  2. iOS13适配深色模式(Dark Mode)总结

    iOS13适配深色模式(Dark Mode)总结 好像大概也许是一年前, Mac OS系统发布了深色模式外观, 看着挺刺激, 时至今日用着也还挺爽的 终于,随着iPhone11等新手机的发售, iOS ...

  3. 实现页面适配_微信公众号文章页面适配深色模式

    最近安卓微信7.0.10正式版发布,更新过后,很多用户发现,之前在测试版中对系统深色模式的适配功能被取消了,小伙伴们对此很是不满,好在Android 10系统手机用户占比很少,影响范围还不是很大,并且 ...

  4. android开发适配深色模式,手机不支持深色模式,如何用软件解决深色模式的问题?(附有系统全局深色模式实现方法...

    本帖最后由 巷子口的你 于 2020-8-8 07:57 编辑 1.92允许通过设置为助手应用来饮捷切频深色模式(设置入口一般为系统默认应用-助手和语音输人, MIU需要设置为语音助手)提醒:稳定模式 ...

  5. android自动切换暗色,Android 适配深色模式的总结

    Android Q 推出了深色模式,其实 Android 9 就有了,部分厂商小米,三星就在系统 Android 9 加入了深色模式的开关. Android 提供了一套夜间模式主题,继承 Theme. ...

  6. SVG公众号排版『适配深色模式图片二维码可识别可点击』模板代码

    二维码可识别图片不弹出 <!DOCTYPE html> <html> <head><meta charset="UTF-8" />& ...

  7. H5项目适配系统深色模式方案总结

    文章目录 一.背景 二.问题 三.H5项目适配深色模式方案 1.声明 color-scheme 1.1meta 1.2CSS 2.通过 CSS 媒体查询 3.图片适配 4. JavaScript中判断 ...

  8. H5项目适配系统深色模式方案

    一.背景 随着 iOS 13 的发布,深色模式(Dark Mode)越来越多地出现在大众的视野中,支持深色模式已经成为现代移动应用和网站的一个潮流,前段时间更是因为微信的适配再度引起热议.深色模式不仅 ...

  9. 网页深色模式样式适配(web dark mode support)

    目前iOS,macos都有了深色模式,而最近微信最新版也做了深色模式(dark mode)适配,我试了下,手机切换时页面效果样式是实时刷新的.于是就想着web怎么能够监听深色模式,并设置样式.查了资料 ...

最新文章

  1. 只需4步,自己搞个 Spring Boot Starter !
  2. 《C++ Primer Plus》第8章 函数探幽 学习笔记
  3. PHP中单引号和双引号的区别
  4. 实验吧—Web——WP之 上传绕过
  5. I must be strong and carry on
  6. java rf14bug_hadoop2.7.0集群,使用中遇到的bug及解决办法
  7. html项目案例_非常时期的健身IP案例-营销100案之8
  8. python的装饰器和find函数的使用
  9. dell服务器进系统失败,如何解决Dell服务器系统开机提示错误
  10. 《教父II:西西里人》 shbp--3
  11. 你所不知道的网盘搜索引擎
  12. 用计算机亩换算成平方,亩换算平方(平方米换算亩计算器)
  13. Python将csv文件以某列为条件分类切割
  14. 旺店通与用友U8集成解决方案
  15. goto在golang中的用法
  16. php报错 Function name must be a string in xxxx解决
  17. 怎么刷网站关键词流量​?
  18. PDCA 离开了日本就水土不服?
  19. python创建一个空集合_python空集合如何表示
  20. Android动画案例(一) 帧动画

热门文章

  1. 阿里云ecs云服务器建立wordpress个人博客教程
  2. 【Python】从爬虫开始吧——爬取妹子图整站
  3. 无法从命令行或调试器启动服务,必须首先安装Windows服务....。在“安装”阶段发生异常。 System.Security.SecurityException:未找到源
  4. 有声小说配音兼职平台,十大正规配音兼职平台
  5. This beta version of Typora is expired,please download and install a newe最新解决方案
  6. 检查 Windows 版本与 Windows 更新
  7. 一位非IT人士的见血封喉 SCM与ERP的异同和尴尬(1)
  8. mPOS安全提升之路
  9. Kubectl :--v 接口调试,以及设置日志输出详细程度
  10. 计算机技术指标主频是指微机的时钟频率,计算机中央处理器(CPU)的主要性能指标...