歡迎登錄個人我的網站: www.sketchk.xyzswift
Dark Mode 做爲 iOS 13 的新特性之一,爲 App 的呈現方式帶來了更多的可能,但也給開發者帶來了大量的適配工做。app
在適配 Dark Mode 的過程當中,開發者只須要思考清楚下面三個問題便可:ide
在 iOS 13 中,因爲 UIView 和 UIViewController 這些基類已經遵循了 UITraitEnvironment 協議,咱們能夠經過 UITraitCollection 判斷 App 當前的 Apparance 狀態。代碼以下所示:網站
Swift 的代碼以下:ui
let isDark = UITraitCollection.current.userInterfaceStyle == .dark
let realColor = UIColor.systemBackground.resolvedColor(with: traitCollection)
let realImage = UIImage(named: "Header")?.imageAsset?.image(with: traitCollection)
複製代碼
Objective-C 的代碼以下:spa
BOOL isDark = [UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark? YES: NO;
UIColor *realColor = [[UIColor systemBackgroundColor] resolvedColorWithTraitCollection:traitCollection];
UIImage *image = [[[UIImage imageNamed:@"Header"] imageAsset] imageWithConfiguration:traitCollection]
複製代碼
須要注意的是,上方代碼中咱們調用了 [UITraitCollection currentTraitCollection],但 UITraitCollection 並非以單例的方式存在,每一個 view 和 ViewController 都有一個屬於自身的 UITraitCollection 類型的屬性。設計
因此咱們也徹底能夠經過 traitCollection.
或者 self.traitCollection
的方式獲取此屬性,3d
不過,也不是全部方法執行前,UIKit 都會幫咱們作把 UITraitCollection.current 設置爲 self.traitCollection,只有在如下這些方法中會執行此操做:code
UIView | UIViewController | UIPresentationController |
---|---|---|
draw() | ||
layoutSubview() | viewWillLayoutSubviews() viewDidLayoutSubviews() |
containerViewWillLayoutSubviews() containerViewDidLayoutSubviews() |
traitCollectionDidChange() tintColorDidChange() |
traitCollectionDidChange() | traitCollectionDidChange() |
在實際寫代碼前,咱們還需更深入的理解適配 Dark Mode 這項工做背後的含義。cdn
雖然 Apple 給出了了許多好用的 API 幫助開發者迅速完成 Dark Mode 的適配,但這是你應該用的 API 麼?例如系統給出了 systemBlue
, systemGray
等 API 到底意味着什麼?
這裏須要明確的是 systemBlue
這些 API 本質上在 Apple 的 Human Interface Guidelines 下制定的 Dark Mode 配色,並不表明這些配色就應該無腦的用在你的 App 上。
Apple 原生的 App 大多數是以白色或淺色系爲基調,因此在此設計規範下,它提供的 API 下能夠很好的作 Light Mode 和 Dark Mode 的切換,且 App 的視覺效果十分驚豔。
但若是你的 App 不是淺色系,若是像淘寶的橙色系,餓了麼的藍色系,甚至多閃的暗色系,他們若是直接用 Apple 的設計規範,從視覺體驗上來講,可能就顯得有點不那麼匹配了,並且 Apple 提供給你的這些 API 就顯得有點多餘。
因此在動手前你須要明確本身的需求,Apple 提供的這些設計規範是否符合 App 當前的調性,或者設計師和你的預期麼?
若是是的,請大膽的使用 Apple 提供的 API 吧。關於這些 API 表明的樣式徹底能夠在 Apple 提供的 Human Interface Guidelines 和 Resource 中找到。
若是不是,請結合自身 App 的設計規範,抽象出一箇中間層或者 SDK 來定義這些變化。
與 Dark Mode 相關的 API 有如下幾個特色
UIActivityIndicatorView
的 style 屬性從 gray
, white
, whiteLarge
變成了 large
和 medium
,UIStatusBar
的 style 屬性從 default
和 lightContent
變成了 default
和 lightContent
和 darkContent
,其中 default
樣式會根據當前的模式展現不一樣的顏色這裏的核心問題就是在 Appearance 切換後,哪些元素須要適配?
大部分人的第一直覺會認爲是控件顏色,例如控件的背景色和控件的內容顏色,那還有別的元素麼?
顯然是有的,須要考慮的類型大致有兩種,一種是圖片素材,一種是模糊效果,咱們先簡單闡述下這兩個元素適配的必要性
圖片素材的適配必要性顯而易見,例如 tab bar 或者 navigation bar 裏的 icon,在切換爲 dark mode 後,那些原先就是黑色的 icon 在 dark mode 下會變得難以辨識。
若是說圖片素材要解決的是辨識度問題,那麼模糊效果須要解決的就是協調性問題,若是在 dark 模式下,模糊效果總體過於泛白就會顯得有些格格不入,進而影響用戶體驗。
上面說明了必要性,咱們來講說針對不一樣元素的適配方案
若是系統顏色符合你的預期,經過下面的語句就能夠實現 dark mode 的適配
self.view.backgroundColor = .systemBackground
複製代碼
若是系統顏色不符合你的預期,經過下面的語句來實現 dark mode 的適配
self.textView.textColor = .myDynamicColor
extension UIColor {
class var myDynamicColor: UIColor {
get {
.init(dynamicProvider: { (traitCollection) -> UIColor in
if traitCollection.userInterfaceStyle == .dark {
return UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 1)
} else {
return UIColor(displayP3Red: 255, green: 255, blue: 255, alpha: 1)
}
})
}
}
}
複製代碼
一般狀態下,App 內的組件都是直接使用系統提供的 UIBlurEffectView 組件,經過下面的代碼就能夠快速完成 Dark Mode 的匹配,固然 style 裏面的 system
開頭的枚舉值須要你根據自身的狀況進行選擇。
let blurView = UIVisualEffectView(effect: UIBlurEffect.init(style: .systemMaterial))
複製代碼
若是你的模糊控件是自行開發的,那麼你就須要根據自身 App 的設計規範從新開發一套 API 來知足使用。
咱們能夠利用 xcassets 中爲圖片控件新增的 Apperance 屬性,分別設置兩種模式下所使用到的圖片,例如在深色模式下展現日落的照片,而在普通模式下展現日出的照片。
恭喜你,至此你已經掌握了適配 Dark Mode 的全部基本知識點,剩下須要作的就是實戰了。
若是你還想更深刻理解 dark mode 的相關信息,能夠觀看 WWDC 2019 Session 214: Implementing Dark Mode on iOS