iOS13 暗黑模式(Dark Mode)适配之OC版
目录
- 一、适配Dark Mode
- 颜色适配
- 图片适配
- 二、获取当前模式(Light or Dark)
- 三、其余内容
- 四、总结
首先看看我们的效果图:
适配效果图
一、适配Dark Mode
开发者主要从颜色和图片两个方面进行适配,我们不需要关心切换模式时该如何操作,这些都由系统帮我们实现
1 颜色适配
- iOS13 之前
UIColor只能表示一种颜色,而从 iOS13 开始UIColor是一个动态的颜色,在Light Mode和Dark 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进去 - 当系统在
LightMode和DarkMode之间相互切换时就会触发此回调 - 这个
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];?? 注意!!!
- 当我们强行设置当前viewController为Dark 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)
)
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » iOS13 暗黑模式(Dark Mode)适配之OC版