參考原文
-
一案训、適配Dark Mode
顏色適配
圖片適配 -
二斤程、獲取當(dāng)前模式(Light or Dark)
-
三、其他內(nèi)容
-
四专筷、總結(jié)
一、適配Dark Mode
1 顏色適配
- iOS13 之前
UIColor
只能表示一種顏色蒸苇,而從 iOS13 開始UIColor
是一個(gè)動(dòng)態(tài)的顏色磷蛹,在Light Mode
和Dark Mode
可以分別設(shè)置不同的顏色。 - iOS13系統(tǒng)提供了一些動(dòng)態(tài)顏色
) 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);
① 實(shí)例
[self.view setBackgroundColor:[UIColor systemBackgroundColor]];
[self.titleLabel setTextColor:[UIColor labelColor]];
[self.detailLabel setTextColor:[UIColor placeholderTextColor]];
系統(tǒng)UIColor樣式
用法和iOS13之前的一樣溪烤,使用系統(tǒng)提供的這些動(dòng)態(tài)顏色味咳,不需要其他的適配操作
② 自定義動(dòng)態(tài)UIColor
在實(shí)際開發(fā)過程,系統(tǒng)提供的這些顏色還遠(yuǎn)遠(yuǎn)不夠檬嘀,因此我們需要?jiǎng)?chuàng)建更多的動(dòng)態(tài)顏色
初始化動(dòng)態(tài)UIColor方法
iOS13 UIColor增加了兩個(gè)初始化方法槽驶,使用以下方法可以創(chuàng)建動(dòng)態(tài)UIColor
注:一個(gè)是類方法,一個(gè)是實(shí)例方法
+ (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);
這兩個(gè)方法要求傳一個(gè)block進(jìn)去
當(dāng)系統(tǒng)在LightMode和DarkMode之間相互切換時(shí)就會(huì)觸發(fā)此回調(diào)
這個(gè)block會(huì)返回一個(gè)UITraitCollection類
我們需要使用其屬性userInterfaceStyle鸳兽,它是一個(gè)枚舉類型掂铐,會(huì)告訴我們當(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);
實(shí)例
UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {
if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {
return [UIColor redColor];
}
else {
return [UIColor greenColor];
}
}];
[self.bgView setBackgroundColor:dyColor];
2.圖片適配
- 打開
Assets.xcassets
- 新建一個(gè)
Image set
- 打開右側(cè)工具欄,點(diǎn)擊最后一欄揍异,找到
Appearances
全陨,選擇Any,Dark
- 將兩種模式下不同的圖片資源都拖進(jìn)去
- 使用該圖片
3.獲取當(dāng)前模式(Light or Dark)
有時(shí)候我們需要知道當(dāng)前處于什么模式蒿秦,并根據(jù)不同的模式執(zhí)行不同的操作
iOS13中CGColor依然只能表示單一的顏色
通過調(diào)用UITraitCollection.currentTraitCollection.userInterfaceStyle
獲取當(dāng)前模式
實(shí)例
if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
[self.titleLabel setText:@"DarkMode"];
}
else {
[self.titleLabel setText:@"LightMode"];
}
}
其他
1.監(jiān)聽模式切換
有時(shí)我們需要監(jiān)聽系統(tǒng)模式的變化烤镐,并作出響應(yīng)
那么我們就需要在需要監(jiān)聽的viewController中蛋济,重寫下列函數(shù)
// 注意:參數(shù)為變化前的traitCollection
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection;
// 判斷兩個(gè)UITraitCollection對象是否不同
- (BOOL)hasDifferentColorAppearanceComparedToTraitCollection:(UITraitCollection *)traitCollection;
① 示例
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
// trait發(fā)生了改變
if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
// 執(zhí)行操作
}
}
2.CGColor適配
我們知道iOS13后棍鳖,UIColor能夠表示動(dòng)態(tài)顏色,但是CGColor依然只能表示一種顏色碗旅,那么對于CALayer等對象如何適配暗黑模式呢?當(dāng)然是利用上一節(jié)提到的監(jiān)聽模式切換的方法啦渡处。
- (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;
}
??!!! 設(shè)置layer顏色都是在traitCollectionDidChange中,意味著如果沒有發(fā)生模式切換祟辟,layer將會(huì)沒有顏色医瘫,需要設(shè)置一個(gè)基本顏色
3.模式切換時(shí)打印log
模式切換時(shí)自動(dòng)打印log,就不需要我們一次又一次的執(zhí)行po命令了
- 在Xcode菜單欄Product->Scheme->Edit Scheme
- 選擇Run->Arguments->Arguments Passed On Launch
- 添加以下命令即可
-UITraitCollectionChangeLoggingEnabled YES
4.強(qiáng)行設(shè)置App模式
當(dāng)系統(tǒng)設(shè)置為Light Mode時(shí)旧困,對某些App的個(gè)別頁面希望一直顯示Dark Mode下的樣式醇份,這個(gè)時(shí)候就需要強(qiáng)行設(shè)置當(dāng)前ViewController的模式了
// 設(shè)置當(dāng)前view或viewCongtroller的模式
@property(nonatomic) UIUserInterfaceStyle overrideUserInterfaceStyle;
示例
// 設(shè)置為Dark Mode即可
[self setOverrideUserInterfaceStyle:UIUserInterfaceStyleDark];
?? 注意!!!
當(dāng)我們強(qiáng)行設(shè)置當(dāng)前viewController為Dark Mode后稼锅,這個(gè)viewController下的view都是Dark Mode
由這個(gè)ViewController present出的ViewController不會(huì)受到影響,依然跟隨系統(tǒng)的模式
要想一鍵設(shè)置App下所有的ViewController都是Dark Mode僚纷,請直接在Window上執(zhí)行overrideUserInterfaceStyle
對window.rootViewController強(qiáng)行設(shè)置Dark Mode也不會(huì)影響后續(xù)present出的ViewController的模式
5.NSAttributedString優(yōu)化
對于UILabel矩距、UITextField、UITextView怖竭,在設(shè)置NSAttributedString時(shí)也要考慮適配Dark Mode锥债,否則在切換模式時(shí)會(huì)與背景色融合,造成不好的體驗(yàn)
不建議的做法
NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16]};
NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案" attributes:dic];
推薦的做法
// 添加一個(gè)NSForegroundColorAttributeName屬性
NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor labelColor]};
NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案" attributes:dic]
總結(jié)
總的來說痊臭,iOS13主要有以下變化:
1.支持 Dark Mode
2.UIColor變?yōu)閯?dòng)態(tài)顏色
3.更新StatusBar樣式
4.更新UIActivityIndicatorView樣式