如果是老项目,改动太多,不想适配暗黑模式的话,有个偷懒的方法。或者还没适配完又不想给用户看,可以先暂时全局关闭暗黑模式:在 Info.plist 文件中,添加 key 为 User Interface Style,类型为 String,value 设置为 Light 即可。

追求极致体验,就要完全适配,所有页面没适配好的统统适配一遍,分为以下几种情况。

  • 一、适配Dark Mode

    • 颜色适配
    • 图片适配
  • 二、获取当前模式(Light or Dark)
  • 三、其他内容
  • 四、总结

首先看看我们的效果图:

适配效果图

一、适配Dark Mode

开发者主要从颜色和图片两个方面进行适配,我们不需要关心切换模式时该如何操作,这些都由系统帮我们实现

1 颜色适配

  • iOS13 之前 UIColor只能表示一种颜色,而从 iOS13 开始UIColor是一个动态的颜色,在Light ModeDark Mode可以分别设置不同的颜色。
  • iOS13系统提供了一些动态颜色
@property (class, nonatomic, readonly) UIColor *systemBrownColor        API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *systemIndigoColor       API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *systemGray2Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGray3Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGray4Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGray5Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGray6Color        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *labelColor              API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *secondaryLabelColor     API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *tertiaryLabelColor      API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *quaternaryLabelColor    API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *linkColor               API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *placeholderTextColor    API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *separatorColor          API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *opaqueSeparatorColor    API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *systemBackgroundColor                   API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *secondarySystemBackgroundColor          API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *tertiarySystemBackgroundColor           API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGroupedBackgroundColor            API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *secondarySystemGroupedBackgroundColor   API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *tertiarySystemGroupedBackgroundColor    API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemFillColor                         API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *secondarySystemFillColor                API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *tertiarySystemFillColor                 API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *quaternarySystemFillColor               API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);

① 实例


[self.view setBackgroundColor:[UIColor systemBackgroundColor]];
[self.titleLabel setTextColor:[UIColor labelColor]];
[self.detailLabel setTextColor:[UIColor placeholderTextColor]];

② 效果展示

系统UIColor样式

用法和iOS13之前的一样,使用系统提供的这些动态颜色,不需要其他的适配操作

③ 自定义动态UIColor

在实际开发过程,系统提供的这些颜色还远远不够,因此我们需要创建更多的动态颜色

初始化动态UIColor方法

iOS13 UIColor增加了两个初始化方法,使用以下方法可以创建动态UIColor
注:一个是类方法,一个是实例方法


+ (UIColor *)colorWithDynamicProvider:(UIColor * (^)(UITraitCollection *))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
- (UIColor *)initWithDynamicProvider:(UIColor * (^)(UITraitCollection *))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
  • 这两个方法要求传一个block进去
  • 当系统在LightModeDarkMode之间相互切换时就会触发此回调
  • 这个block会返回一个UITraitCollection
  • 我们需要使用其属性userInterfaceStyle,它是一个枚举类型,会告诉我们当前是LightMode还是DarkMode
typedef NS_ENUM(NSInteger, UIUserInterfaceStyle) {UIUserInterfaceStyleUnspecified,UIUserInterfaceStyleLight,UIUserInterfaceStyleDark,
} API_AVAILABLE(tvos(10.0)) API_AVAILABLE(ios(12.0)) API_UNAVAILABLE(watchos);

实例

UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {return [UIColor redColor];}else {return [UIColor greenColor];}}];[self.bgView setBackgroundColor:dyColor];

效果展示

自定义UIColor效果

接下来我们看看如何适配图片

2.图片适配

  • 打开Assets.xcassets
  • 新建一个Image set

默认显示效果

  • 打开右侧工具栏,点击最后一栏,找到Appearances,选择Any,Dark

    侧边栏

  • 将两种模式下不同的图片资源都拖进去

两种不同模式

  • 使用该图片
[_logoImage setImage:[UIImage imageNamed:@"icon_logo"]];

最终效果图

大功告成,完成颜色和图片的Dark Mode适配,是不是很easy呢

① 获取当前模式(Light or Dark)

有时候我们需要知道当前处于什么模式,并根据不同的模式执行不同的操作
iOS13中CGColor依然只能表示单一的颜色
通过调用UITraitCollection.currentTraitCollection.userInterfaceStyle
获取当前模式

实例

if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {[self.titleLabel setText:@"DarkMode"];}else {[self.titleLabel setText:@"LightMode"];}

三、其他

1.监听模式切换

有时我们需要监听系统模式的变化,并作出响应
那么我们就需要在需要监听的viewController中,重写下列函数

// 注意:参数为变化前的traitCollection
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection;// 判断两个UITraitCollection对象是否不同
- (BOOL)hasDifferentColorAppearanceComparedToTraitCollection:(UITraitCollection *)traitCollection;

① 示例


- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {[super traitCollectionDidChange:previousTraitCollection];// trait发生了改变if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {// 执行操作}}

2.CGColor适配

我们知道iOS13后,UIColor能够表示动态颜色,但是CGColor依然只能表示一种颜色,那么对于CALayer等对象如何适配暗黑模式呢?当然是利用上一节提到的监听模式切换的方法啦。

① 方式一:resolvedColor

// 通过当前traitCollection得到对应UIColor
// 将UIColor转换为CGColor
- (UIColor *)resolvedColorWithTraitCollection:(UITraitCollection *)traitCollection;

实例

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {[super traitCollectionDidChange:previousTraitCollection];UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {return [UIColor redColor];}else {return [UIColor greenColor];}}];UIColor *resolvedColor = [dyColor resolvedColorWithTraitCollection:previousTraitCollection];layer.backgroundColor = resolvedColor.CGColor;

② 方式二:performAsCurrent

// 使用当前trainCollection调用此方法
- (void)performAsCurrentTraitCollection:(void (^)(void))actions;

示例

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {[super traitCollectionDidChange:previousTraitCollection];UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {return [UIColor redColor];}else {return [UIColor greenColor];}}];[self.traitCollection performAsCurrentTraitCollection:^{layer.backgroundColor = dyColor.CGColor;}];}

方式三:最简单的方法

直接设置为一个动态UIColor的CGColor即可

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {[super traitCollectionDidChange:previousTraitCollection];UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {return [UIColor redColor];}else {return [UIColor greenColor];}}];layer.backgroundColor = dyColor.CGColor;
}

⚠️!!! 设置layer颜色都是在traitCollectionDidChange中,意味着如果没有发生模式切换,layer将会没有颜色,需要设置一个基本颜色

3.模式切换时打印log

模式切换时自动打印log,就不需要我们一次又一次的执行po命令了

  • 在Xcode菜单栏Product->Scheme->Edit Scheme
  • 选择Run->Arguments->Arguments Passed On Launch
  • 添加以下命令即可
    • -UITraitCollectionChangeLoggingEnabled YES
    • 模式切换打印log

4.强行设置App模式

当系统设置为Light Mode时,对某些App的个别页面希望一直显示Dark Mode下的样式,这个时候就需要强行设置当前ViewController的模式了

// 设置当前view或viewCongtroller的模式
@property(nonatomic) UIUserInterfaceStyle overrideUserInterfaceStyle;

示例

// 设置为Dark Mode即可
[self setOverrideUserInterfaceStyle:UIUserInterfaceStyleDark];

⚠️ 注意!!!

  • 当我们强行设置当前viewControllerDark Mode后,这个viewController下的view都是Dark Mode
  • 由这个ViewController present出的ViewController不会受到影响,依然跟随系统的模式
  • 要想一键设置App下所有的ViewController都是Dark Mode,请直接在Window上执行overrideUserInterfaceStyle
  • window.rootViewController强行设置Dark Mode也不会影响后续present出的ViewController的模式

5.NSAttributedString优化

对于UILabel、UITextField、UITextView,在设置NSAttributedString时也要考虑适配Dark Mode,否则在切换模式时会与背景色融合,造成不好的体验

不建议的做法

NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16]};
NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案" attributes:dic];

推荐的做法

// 添加一个NSForegroundColorAttributeName属性
NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor labelColor]};
NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案" attributes:dic];

五、总结

总的来说,iOS13主要有以下变化:
1.支持 Dark Mode
2.UIColor变为动态颜色
3.更新StatusBar样式
4.更新UIActivityIndicatorView样式

完整iOS13新特性请参考以下文章:
iOS13 新特性简介
iOS13-适配夜间模式/深色外观(Dark Mode)
iOS13 暗黑模式(Dark Mode)适配之OC版

iOS13适配之暗黑模式(Dark Mode)相关推荐

  1. (0105)iOS开发之iOS13 暗黑模式(Dark Mode)适配

    导读: Material Design & iOS 13 黑暗模式总结探索 暗黑模式苹果开发文档 如何不进行系统切换样式的适配 注意 同一工程内多个Assets文件在打包后,就会生成一个Ass ...

  2. ios 暗黑模式 Dark Mode

    *ios 暗黑模式 Dark Mode 一.UITraitCollection 为表征 size class 而生,用来区分设备.你可以在它身上获取到足以区分所有设备的特征 API: (1)判断当前设 ...

  3. 浏览器暗黑模式-Dark深色模式

    浏览器暗黑模式-Dark深色模式 文章目录 浏览器暗黑模式-Dark深色模式 背景 edge浏览器 chrome浏览器 dark reader 插件 最后 背景 最近看电脑看的时间比较长,眼睛疲劳,看 ...

  4. ant-design-vue 自由切换 暗黑模式dark

    ant-design-vue 自由切换 暗黑模式dark 项目演示 代码 思路 引入 dark.css 文件 动态切换 prefixCls 实现效果 我们来看看官网怎么说的 官网地址 除了 less ...

  5. iOS开发之iOS13 暗黑模式(Dark Mode)适配

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/shifang07/article/de ...

  6. Android webView适配H5暗黑模式

    第一步 首先Android 必须是Q 就是10.0才能支持暗黑模式 第二步 设置Android webView暗黑模式 WebViewFeature必须引入这个包 implementation 'an ...

  7. Xcode10 开启暗黑模式(dark mode)

    先来张效果图: 第1步: 去开发者下载中心: https://developer.apple.com/download/ 安装 macOS Mojave 10.14 和Xcode10. 第2步: 在终 ...

  8. 京东 App适配 iOS 暗黑模式业务实践

    以下文章来源于京东零售技术,作者平台研发姚琦 什么是暗黑模式? iOS 13 苹果推出了暗黑模式,暗黑模式在夜间可以更好的保护视力,也可以节省 App 电量消耗.但是 Apple 提供的暗黑模式只支持 ...

  9. iOS13 不使用暗黑模式

    网上google搜到的, 关于"不使用暗黑模式"的解决办法都是: 这是写法确实是有效的,但是上传appstore提交审核,会报错App Store Connect Operatio ...

最新文章

  1. maven私有库搭建
  2. 6.1 从分析到设计
  3. openstack API debug OpenstackEveryProject_CLI,curl_based
  4. 牛客 - 双流机场(思维)
  5. MFC 缩放和显示IplImage
  6. py获取前端的参数_微前端 qiankun 项目实践
  7. CCF-CSP认证201312-1(出现次数最多的数)
  8. UVA - 11059 Maximum Product-暴力枚举
  9. 实例9:python
  10. cloud一分钟 | 腾讯金融云总经理胡利明:腾讯云服务金融的“加减 乘除”法。...
  11. jsonp react 获取返回值_Django+React全栈开发:文章列表
  12. sql设置自增字段的标识行
  13. 【数据库系统设计】数据库安全性
  14. oracle dblink 20001,解决ORA-02021: 不允许对远程数据库进行 DDL 操作下面通过DBLINK调用远程过程来执行这样的操作。...
  15. 两直线平行交叉相乘_初中数学几何公式、定理梳理,太全了!老师都转发了!...
  16. 开发中积累的单词800
  17. 解决office怎么卸载都卸载不干净的终极办法。
  18. Docker配置文件位置
  19. JavaWeb的体育用品商店的设计与实现
  20. C4D快速入门教程——软件界面介绍

热门文章

  1. jmeter html报告乱码,JMeter3.0图形化HTML报告中文乱码问题处理
  2. 【面试整理】 应届JAVA(初级)的一次面试经过
  3. 细说值传递、引用传递和地址传递
  4. 新版购物车类,加入查找功能以及完善错误处理功能
  5. 如何利用计算机窃取信息,哪些计算机病毒会窃取电脑信息
  6. 【讲座】北大拱玉书教授:苏美尔文明和中国古代文明的几个相同文化现象 笔记
  7. Tx2上人体姿态估计AlphaPose配置安装教程
  8. DATASTAGE——一DATASTAGE经验积累
  9. 华为分屏怎么用_用一台12999元的手机是怎么样的体验?用过华为Mate20 RS以后,我是服气的!...
  10. 三星android是啥意思,三星Android系统文件夹全解