作者:道乐技术

谣言来源

说起深色模式,就不得不回顾一下苹果和微信“神仙打架”的谣言,这个瓜必须得吃一下! 原来是有小道消息传出:“苹果警告微信,5 月份不更新深色模式的话,就要从 App Store 下架。”

然而晚些时候,微信团队就跑出来辟谣说:“根本没有这回事,我们只是跟苹果一起探索微信在iOS系统的深色模式。”

其实人家根本没有威胁开发者更新深色模式,只是苹果规定在 5 月之前,旧App要进行更新、新 App 要上架,都必须使用 iOS 13 的 SDK (现在苹果把时间 延长到6月了),而iOS 13 SDK 里包含一套,开发深色模式的工具。

于是乎,有人把“苹果要求开发者使用 iOS 13 SDK”,与“苹果要求开发者更新深色模式”,这两句话划上等号。

但这个等号是不成立的。前者是真的,后面那句只是臆想出来的。

咱们iOS程序猿小哥说:(瞎带什么节奏…害我查了一天资料,工作又做不完了)

深色模式的用处

为何深色模式如此受关注,并对其有强烈的期待感?

相对于繁忙工作的的白天,其实大家更多刷手机的时间是在晚间。白底色的背景光对于黑色会散发出更多的蓝光,尤其在夜间相对较暗的环境下,对眼睛的伤害更为严重。黑色模式的出现,对于熬夜党来说,无疑是一大福音。

另外,颜色深色化的改变,也会让手机达到更加省电的目的。

(图片源自网络)

根据国外up主实验发现,当屏幕亮度越亮时,“深色模式”省电效果会更明显,如:将屏幕亮度调暗至100尼特和最亮300尼特,分别获得以下数据:100尼特(低亮度):深色模式iPhone 耗损8% 电量,浅色模式则为13% 电量300尼特(高亮度):深色模式iPhone 耗损10% 电量,浅色模式则为22% 电量可见,省电效果还是比较不错的(不过,能够让iPhone 在深色模式下达到省电效果,还是需要使用OLED 屏幕才能够实现。)

出门少带块充电宝,还是很实用的~

话不多说,让大家亲自体验一把BAT大佬和苹果大佬打造的“护眼模式”~

效果这么炫酷,该如何设置?

怎么设置

适配Dark Mode

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

1. 颜色适配

iOS13之前UIColor只能表示一种颜色,而从iOS13开始UIColor是一个动态的颜色,在Light Mode和Dark Mode中可以分别设置不同的颜色。iOS13系统提供了一些动态颜色。如下:

① 实例:

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

② 效果展示:

使用系统提供的这些动态颜色,不需要其他的适配操作

③ 自定义动态UIColor:

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

iOS13中UIColor增加了两个初始化方法,使用以下方法可以创建动态UIColor

+ (UIColor *)colorWithDynamicProvider:(UIColor * (^)(UITraitCollection *))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
- (UIColor *)initWithDynamicProvider:(UIColor * (^)(UITllection *))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);

这两个方法要求传一个block进去,当系统在LightMode和DarkMode之间相互切换时就会触发此回调,这个block会返回一个UITraitCollection类,而我们需要使用其属性userInterfaceStyle,因为它是一个枚举类型,会告诉我们当前是LightMode还是DarkMode。

实例:


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

效果展示:

除了通过代码初始化颜色以外,也可通过配置形式适配:

打开Assets.xcassets,新建一个Color set,打开右侧工具栏,点击最后一栏,找到Appearances,选择Any,Dark

使用该颜色:

[self.bgView setBackgroundColor:[UIIColor imageNamed:@"bgColor"]];

2. 图片适配

同理颜色适配,打开Assets.xcassets,新建一个Image set,打开右侧工具栏,点击最后一栏,找到Appearances,选择Any,Dark,将两种模式下不同的图片资源都拖进去

使用该图片:

[self.bgView setBackgroundColor:[UIIColor imageNamed:@"bgColor"]];

这样颜色和图片的Dark Mode适配就大功告成了,也相对的比较简单。

获取当前模式

有时候我们需要知道当前处于什么模式,并根据不同的模式执行不同的操作

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. 强行设置App模式

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

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

示例:

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

注意!!!

当我们强行设置当前viewController为Dark Mode后,这个viewController下的view都是Dark Mode

而这个ViewController present出的ViewController不会受到影响,依然跟随系统的模式。

3. NSAttributedString优化

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

4. Status Bar

之前 Status Bar 有两种状态,default(文字黑色)和 lightContent(文字白色)

现在 Status Bar 有三种状态,default(自动选择黑色或白色), darkContent(文字黑色) 和 lightContent(文字白色)

现在的 darkContent 对应之前的 default,现在的 default 会根据情况自动选择 darkContent 和 lightContent

5. UIActivityIndicatorView

之前的 UIActivityIndicatorView 有三种 style 分别为 whiteLarge, white 和 gray,现在全部废弃。

增加两种 style 分别为 medium 和 large,指示器颜色用 color 属性修改。

6. 模式切换时打印log

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

在Xcode菜单栏Product->Scheme->Edit Scheme

选择Run->Arguments->Arguments Passed On Launch

添加以下命令即可:

-UITraitCollectionChangeLoggingEnabled YES

总结与拓展

总的来说,iOS13深色模式主要有以下变化:

1. 支持Dark Mode

2. UIColor变为动态颜色、图片可设置Dark Mode模式

3. 更新Status Bar样式

4. 更新UIActivityIndicatorView样式

当然,如果说应用不想适配深色模式可以关闭深色模式,一劳永逸:

在Info.plist文件中添加Key:User Interface Style,值类型设置为String,值为Light,就可以不管在什么模式下,软件只支持浅色模式,不支持深色模式,如果只想软件支持深色模式,则可以把类型设置为:Dark。

最后,深色模式来临,我们也可以考虑给我们app换波皮肤啊。

安卓版微信的深色模式,也已经完成发布。后续我们也来谈谈安卓和web深色模式

0

道乐研究院