Adapt JDME To iOS13 DarkMode
全域性關閉DarkMode
這是目前採取的方案,讓APP始終保持LightMode
,在info.plsit
檔案中,新增UIUserInterfaceStyle
,值為Light
。
我們要適配DarkMode
,需要將UIUserInterfaceStyle
刪除。
UIColor
iOS13
之前 UIColor
只能表示一種顏色,從iOS13
開始UIColor
是一個動態的顏色,在LightMode
和DarkMode
可以分別設定不同的顏色。
1.首先系統為我們提供了一些動態顏色,使用這種動態顏色,系統直接替我們完成了適配工作。但是系統提供的顏色不符合APP的設計規範的話,一般情況下我們用不到。
@property (class,nonatomic,readonly) UIColor *systemBrownColor API_AVAILABLE(ios(13.0),tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class,readonly) UIColor *systemIndigoColor API_AVAILABLE(ios(13.0),readonly) UIColor *systemGray2Color API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos,watchos);
...
...
複製程式碼
2.自定義動態UIColor
UIColor *textDyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleLight) {
return [UIColor JMEColorWithHexString:@"#2E2D2D"];
} else {
return [UIColor yellowColor];
}
}];
_nameLabel.textColor = textDyColor;
複製程式碼
這樣當系統切換DarkMode
/LightMode
時,會回撥(UIColor * (^)(UITraitCollection *traitCollection))dynamicProvider
這個block,自動為我們更新顏色。
圖片資源
JDME目前使用了Assets.xcassets
來管理圖片,適配DarkMode還是比較方便的。
開啟Assets.xcassets
,設定Appearance
為 Any,Dark
將設計師提供的DarkMode
素材圖片拖入對應的位置,還像往常一樣使用圖片就可以了。
[_logoImage setImage:[UIImage imageNamed:@"icon_logo"]];
複製程式碼
獲取當前模式(LightMode/DarkMode)
上面提到的顏色和圖片,都是由系統來幫我們完成切換的。但是在某些場景下,我們需要根據當前的模式,來做一些其他的適配需求。
我們可以在 UIViewController
或者 UIView
中呼叫traitCollection.userInterfaceStyle
來獲取當前檢視的模式。
if (@available(iOS 13.0,*)) {
UIUserInterfaceStyle style = self.traitCollection.userInterfaceStyle;
if (style == UIUserInterfaceStyleLight) {
///TODO:...
} else {
///TODO:...
}
}
複製程式碼
userInterfaceStyle
是iOS12
出現的,但是暗黑模式是iOS13
才有的,所以為了避免不必要的影響,我們還是加上@available(iOS 13.0,*)
的判斷條件。
適當的時候我們可能還需要在drawRect/layoutSubViews等方法中,根據當前的模式重新設定一些色值。
監聽模式的切換(LightMode/DarkMode)
無論是LightMode
還是DarkMode
,使用者都可以切出APP,或者下拉控制中心浮層來隨意切換,所以我們還需要監聽模式的切換。
在 UIView
和 UIViewController
中,當模式切換時,就會觸發下面這個方法
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
if (@available(iOS 13.0,*)) {
if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
///TODO:...
}
} else {
// Fallback on earlier versions
}
}
複製程式碼
CGColor
對於CGColor
,我們可以使用上述的獲取當前模式和監聽模式的方式來處理不同的CGColor
。
Status Bar
之前 Status Bar
有兩種狀態,default
和 lightContent
現在 Status Bar
有三種狀態,default
,darkContent
和 lightContent
現在的 darkContent
對應之前的 default
,現在的 default
會根據情況自動選擇 darkContent
和 lightContent
JDME中設定狀態列顏色的地方有很多,這個還得具體情況具體分析。
UIActivityIndicatorView
之前的 UIActivityIndicatorView
有三種 style
分別為 whiteLarge
,white
和 gray
,現在全部廢棄。
增加兩種 style
分別為 medium
和 large
,指示器顏色用 color
屬性修改。
NSAttributedString
對於UILabel
、UITextField
、UITextView
,在設定NSAttributedString
時也要考慮適配Dark Mode
Storyboard/Xib
xib中,系統提供了使用colorAssets的方式,類似於圖片,但是為了相容低版本,我們還是需要手動程式碼來更改顏色,單獨適配。
第三方模組:
H5 App (WKWebview)
具體由第三方應用做適配
SDK
需要相關團隊做適配。
Flutter Module (Calendar/Login)
儘管 Flutter
在 MaterialApp
中提供了theme
與 darkTheme
兩個入口讓我們設定兩種模式下的顏色及文字樣式,但是還是需要注意一些細節,提供的樣式是否與設計師的要求一致。
注意,Flutter 1.9.1
的版本並沒有適配iOS 13
Status Bar
新增的UIStatusBarStyleDarkContent
。
ReactNative Module (JoySpace)
RN團隊需要做適配。
對於設計師
設計師需要提供一套設計規範,作為底層顏色自動轉換的對映表。我們使用系統提供的方案,可以很快做到顏色轉換來適配暗黑色模式。但是,有些顏色是需要單獨配置的,不能完全遵循底層的顏色轉換,所以,每個頁面都需要設計人員驗收,自動轉換的顏色是否符合整體頁面的UI效果,如果有變動,儘量給出一份暗黑模式的標註圖,然後我們再做單獨配置。所以,對於設計人員和開發需要適配的工作量還是蠻大的。