iOS开发 DarkMode 暗黑模式
一、開發(fā)環(huán)境
Xcode11 正式版 iOS13 beta版本 Mac系統(tǒng): 10.15 beta版本二、適配原理
- 將同一個資源,創(chuàng)建出兩種模式的樣式。系統(tǒng)根據(jù)當(dāng)前選擇的樣式,自動獲取該樣式的資源。
- 每次系統(tǒng)更新樣式時,應(yīng)用會調(diào)用當(dāng)前所有存在的元素調(diào)用對應(yīng)的一些重新方法,進行重繪視圖,可以在對應(yīng)的方法做相應(yīng)的改動
三、資源適配
step1、顏色適配 通過 Assets 配置
在 iOS 11和 Xcode 9 中,我們可以在 Images.xcassets 中添加顏色。
現(xiàn)在我們可以為顏色再配置一個用于暗黑模式的對應(yīng)的顏色。
我們可以選擇 (原彩,深色) 或者 (原彩,深色,夜覽)
step2、圖片適配
打開Assets.xcassets,新建一個Image set,打開右側(cè)工具欄,點擊最后一欄,找到Appearances,同樣可以選擇 (原彩,深色) 或者 (原彩,深色,夜覽),然后在對應(yīng)的位置添加圖片
四、代碼適配
step1、UIColor 適配 語義化顏色介紹加代碼展示
iOS13 之前 UIColor只能表示一種顏色,而從 iOS13 開始UIColor是一個動態(tài)的顏色,在Light Mode和Dark Mode可以分別設(shè)置不同的顏色。
iOS13系統(tǒng)提供了一些動態(tài)顏色。蘋果引入了全新系統(tǒng)顏色和一套根據(jù)顏色使用目的而約定顏色命名的語義化顏色
IOS13系統(tǒng)UIColor增加了兩個初始化方法,使用以下方法可以創(chuàng)建動態(tài)UIColor
注:一個是類方法,一個是實例方法,兩個方法如下:
可以在 block 中判斷 traitCollection.userInterfaceStyle,根據(jù)系統(tǒng)模式設(shè)置返回的顏色。userInterfaceStyle,是一個枚舉類型,會告訴我們當(dāng)前是LightMode還是DarkMode
typedef NS_ENUM(NSInteger, UIUserInterfaceStyle) {UIUserInterfaceStyleUnspecified,UIUserInterfaceStyleLight,UIUserInterfaceStyleDark, } API_AVAILABLE(tvos(10.0)) API_AVAILABLE(ios(12.0)) API_UNAVAILABLE(watchos);例子
UIColor *color = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {return [UIColor blackColor];} else {return [UIColor whiteColor];}}];step2、CGColor 適配
我們知道iOS13后,UIColor能夠表示動態(tài)顏色,但是CGColor依然只能表示一種顏色,那么對于CALayer等對象如何適配暗黑模式呢?這里提供兩個方法供大家參考:
(1)、通過方法resolvedColorWithTraitCollection得到對應(yīng)UIColor,再將UIColor轉(zhuǎn)換為CGColor
(2)、直接設(shè)置為一個動態(tài)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設(shè)置一個基本顏色,因為兩個方法都是在traitCollectionDidChange中設(shè)置layer的顏色,那么如果沒有發(fā)生模式切換,layer將會沒有顏色
五、獲取當(dāng)前模式以及UITraitCollection介紹,監(jiān)聽模式切換
在 iOS 13 中,我們可以通過 UITraitCollection 來判斷當(dāng)前系統(tǒng)的模式。UIView 和 UIViewController 、UIScreen、UIWindow 都已經(jīng)遵從了UITraitEnvironment 這個協(xié)議,因此這些類都擁有一個叫做 traitCollection 的屬性,在這些類中,我們可以這樣去判斷當(dāng)前 App 的顏色模式:
BOOL isDark = (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark);另外,我們還可以通過 UITraitCollection.current 這個屬性來獲取當(dāng)前 App 的顏色模式但是并不是所有的時候獲取的都是正確的,只有在下面這些方法中,才可以放心的使用這個屬性:
還沒適配完又不想給用戶看,可以先暫時全局關(guān)閉暗黑模式:在 Info.plist 文件中,添加 key 為 User Interface Style,類型為 String,value 設(shè)置為 Light 即可。
有時我們需要監(jiān)聽系統(tǒng)模式的變化,并作出響應(yīng)
那么我們就需要在需要監(jiān)聽的viewController中,重寫下列函數(shù)
示例代碼
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {[super traitCollectionDidChange:previousTraitCollection];// trait發(fā)生了改變if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {// 執(zhí)行操作} }在 iOS 13中,UIView、UIViewController 、UIWindow 有了一個 overrideUserInterfaceStyle 的新屬性,可以覆蓋系統(tǒng)的模式。
單個頁面或視圖關(guān)閉暗黑模式,設(shè)置 overrideUserInterfaceStyle 為對應(yīng)的模式,強制限制該視圖與其子視圖以設(shè)置的模式進行展示,不跟隨系統(tǒng)模式改變進行改變。
示例代碼
?? 注意!!!
- 當(dāng)我們強行設(shè)置當(dāng)前viewController為Dark Mode后,這個viewController下的view都是Dark Mode
- 由這個ViewController present出的ViewController不會受到影響,依然跟隨系統(tǒng)的模式
- 要想一鍵設(shè)置App下所有的ViewController都是Dark Mode,請直接在Window上執(zhí)行overrideUserInterfaceStyle
- 對window.rootViewController強行設(shè)置Dark Mode也不會影響后續(xù)present出的ViewController的模式
六、擴展
step1、模糊效果
- 在 iOS 中,我們創(chuàng)建模糊效果的 UIVisualEffectView 的代碼也會有明確表面明暗的情況。我們需要讓這些模糊效果隨著系統(tǒng)模式的切換而切換。UIKit 提供了新的模糊樣式且是動態(tài)的,會隨著系統(tǒng)模式的改版而自動匹配。
- 在利用 UIVisualEffectView 來創(chuàng)建一些類似模糊的效果時,不要設(shè)置類似 UIBlurEffectStyleExtraLight 這樣帶有明確顏色的效果,而是設(shè)置 UIKit 中新提供的動態(tài)樣式的效果,比如 UIBlurEffectStyleSystemThinMaterialLight 或 UIBlurEffectStyleSystemThinMaterialDark。
step2、啟動圖
如果我們的 App 使用了 LaunchImage 作為啟動屏,那么就應(yīng)該考慮把 LaunchImage 換成 LaunchScreen.storyboard 了,因為在 Xcode 11 中 LaunchImage 并不能像普通的圖片那樣針對深色模式設(shè)置另外的一張圖片。
step3、富文本
給 Attributed String 加上一個 foregroundColor 屬性,設(shè)置動態(tài)的顏色即可。
[attr addAttribute:NSForegroundColorAttributeName value:[UIColor labelColor] range:NSMakeRange(10, 20)];step4、調(diào)試 dark mode
storyboards 和 xib 文件,現(xiàn)在可以切換界面之間的樣式是默認還是暗黑了。
在模擬器上,也可以直接切換暗黑模式進行調(diào)試了。
step5、模式切換打印
- 模式切換時自動打印log,就不需要我們一次又一次的執(zhí)行po命令了
- 在Xcode菜單欄Product->Scheme->Edit Scheme
選擇Run->Arguments->Arguments Passed On Launch
添加以下命令即可 - UITraitCollectionChangeLoggingEnabled YES
step6、Demo地址 YQDarkModeDemo
總結(jié)
以上是生活随笔為你收集整理的iOS开发 DarkMode 暗黑模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于如何将网页做的完整且美观的解决办法
- 下一篇: MIB文件简单分析