如何在iOS13.0上适配深色模式
问题剖析
- 首先,所有 UIKit 本身所提供的 UI 控件(例如 Tabbar) ,只要没有针对颜色等内容特殊设置过,都会自动适配深色模式,这部分是开发者无需关心的
- 开发者可以通过 UIKit 在 UI 控件的颜色、模糊效果、图片这三个方面新提供的 API,来让自己的 App 适配深色模式,具体方式为:
- 给 UI 控件设置颜色的时候,不要设置类似 UIColor.black 这样的绝对值颜色,而是设置 UIKit 中新提供的动态颜色(Dynamic Colors),比如 UIColor.systemBackground
- 利用 UIVisualEffectView 来创建一些类似模糊的效果时,不要设置类似 UIBlurEffect.UIBlurEffectStyleExtraLight 这样带有明确颜色的效果,而是设置 UIKit 中新提供的动态样式的效果,比如 UIBlurEffect.systemThinMaterial
- 利用 xcassets 管理图片和颜色的时候,如果有必要,开发者可以使用 xcassets 在 Xcode 11 中新增的功能,为深色模式额外指定一个图片或者颜色
- 针对那些自定义的 UI 控件,开发者可以通过使用 UITraitCollection ,通过判断当前系统的颜色模式来完成对深色模式的适配
如何在 iOS 上适配深色模式?
解决两个问题:
- 在 iOS 13 中,我们如何判断当前系统的颜色模式?
- 在 iOS 13 中,我们应该对哪些 UI 上的内容适配深色模式?
如何判断当前系统的颜色模式?
在 iOS 13 中,我们可以通过 UITraitCollection 来判断当前系统的颜色模式。在 iOS 系统中,UITraitCollection 已经成为一个管理所有用户界面相关信息的大管家了:而颜色模式的相关信息,被存放在它的 userInterfaceStyle 属性中。
在 iOS 中,我们所熟悉的 UIView 和 UIViewController 、UIScreen、UIWindow 都已经遵从了 UITraitEnvironment 这个协议,因此这些类都拥有一个叫做 traitCollection 的属性,在这些类的方法中,我们可以这样去判断当前 App 的颜色模式:
let isDark = traitCollection.userInterfaceStyle == .dark
除此之外,我们还可以使用 UITraitCollection.current 这个类属性来获取当前 App 的颜色模式。不过需要注意的是在,并不是在所有的地方使用这个 API 都是正确的,只有在下面这些方法中,才可以放心的使用这个 API:
UIView | UIViewController | UIPresentationController |
---|---|---|
draw() | ||
layoutSubview() | viewWillLayoutSubviews() viewDidLayoutSubviews() | containerViewWillLayoutSubviews() containerViewDidLayoutSubviews() |
traitCollectionDidChange() tintColorDidChange() | traitCollectionDidChange() | traitCollectionDidChange() |
哪些内容是我们应该适配的?
- 颜色
- 模糊效果
- 图片
颜色
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
self.textView.textColor = .init(red: 0, green: 1, blue: 2, alpha: 1)
self.te