iOS13 暗黑模式(Dark Mode)适配之OC版
来源:hostname     阅读:609
云上智慧
发布于 2019-08-22 00:50
查看主页

目录

首先看看我们的效果图:

适配效果图

一、适配Dark Mode

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

1 颜色适配

@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);
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.图片适配

默认显示效果两种不同模式
[_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命令了

4.强行设置App模式

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

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

示例

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

?? 注意!!!

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)
)

免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 系统环境 服务器应用
相关推荐
字节跳动/美团/京东:Java岗面试真题揭秘,你能拿多少分?
为了追求更快,CPU、内存、I/O都做了哪些努力?
为什么98%的程序员学编程都会从C语言开始?
VuePress源码阅读(四) -- 「成"站"之日」markdown建站实战篇
超级详细Spring源码探索:容器!
首页
搜索
订单
购物车
我的