QMUI_Theme

使用步驟

首先,請(qǐng)先確認(rèn)你希望以什么樣的形式封裝你的主題對(duì)象,以 QMUI Demo 為例,每個(gè)主題對(duì)應(yīng)一個(gè)配置表,每個(gè)配置表均為一個(gè) NSObject<QDThemeProtocol> * 類(lèi)型。
然后,在盡量早的時(shí)機(jī)初始化 QMUIThemeManager,以保證其他使用顏色、圖片的地方能獲取到正確的值。
QMUI Demo 中選擇的時(shí)機(jī)是:application:didFinishLaunchingWithOptions:。

  1. 先注冊(cè)主題監(jiān)聽(tīng),在回調(diào)里將主題持久化存儲(chǔ)(存到數(shù)據(jù)庫(kù)或者 NSUserDefaults),避免啟動(dòng)過(guò)程中主題發(fā)生變化時(shí)讀取到錯(cuò)誤的值
[[NSNotificationCenter defaultCenter] 
addObserver:self 
selector:@selector(handleThemeDidChangeNotification:) 
name:QMUIThemeDidChangeNotification 
object:nil];
  1. 然后設(shè)置用于生成主題的 block,在需要的時(shí)候 QMUIThemeManager 會(huì)通過(guò)這個(gè) block 得到一個(gè)主題對(duì)象
QMUIThemeManager.sharedInstance.themeGenerator = ^__kindof NSObject * _Nonnull(NSString * _Nonnull identifier) {    
if ([identifier isEqualToString:@"Default"]) return QMUIConfigurationTemplate.new;    
if ([identifier isEqualToString:@"Dark"]) return QMUIConfigurationTemplateDark.new;    
return nil;
};
  1. 再針對(duì) iOS 13 開(kāi)啟自動(dòng)響應(yīng)系統(tǒng)的 Dark Mode 切換// 如果不需要兼容 iOS 13 Dark Mode,則不需要這一段代碼
if (@available(iOS 13.0, *)) {    
// 先通過(guò)這個(gè) block 來(lái)決定當(dāng)系統(tǒng)的 Dark Mode 發(fā)生切換時(shí),要如何映射到業(yè)務(wù)的主題    
QMUIThemeManager.sharedInstance.identifierForTrait = ^__kindof NSObject<NSCopying> * _Nonnull(UITraitCollection * _Nonnull trait) {        
if (trait.userInterfaceStyle == UIUserInterfaceStyleDark) {            
return @"Dark";// 表示當(dāng)檢測(cè)到系統(tǒng)開(kāi)啟了 Dark Mode 時(shí),將主題自動(dòng)切換到 Dark       
 }        
return @"Default";    
};    
// 然后讓 QMUIThemeManager 自動(dòng)響應(yīng)系統(tǒng)的 Dark Mode 切換    
QMUIThemeManager.sharedInstance.respondsSystemStyleAutomatically = YES;
}

做完以上的初始化配置后,剩下的就是業(yè)務(wù)界面的適配了,按照上文提到的,將 color、image、effect 都換成對(duì)應(yīng)的動(dòng)態(tài)對(duì)象。

view.backgroundColor = [UIColor qmui_colorWithThemeProvider:^UIColor * _Nonnull(__kindof QMUIThemeManager * _Nonnull manager, NSString * _Nullable identifier, __kindof NSObject * _Nullable theme) {    return [identifier isEqualToString:@"Dark"] ? UIColor.blackColor : UIColor.whiteColor;}];

layer.backgroundColor = [UIColor qmui_colorWithThemeProvider:^UIColor * _Nonnull(__kindof QMUIThemeManager * _Nonnull manager, NSString * _Nullable identifier, __kindof NSObject * _Nullable theme) {    return [identifier isEqualToString:@"Dark"] ? UIColor.blackColor : UIColor.whiteColor;}].CGColor;

imageView.image = [UIImage qmui_imageWithThemeProvider:^UIImage * _Nonnull(__kindof QMUIThemeManager * _Nonnull manager, NSString * _Nullable identifier, NSObject<QDThemeProtocol> *theme) {    return [UIImage imageNamed:[identifier isEqualToString:@"Dark"] ? @"image_dark" : @"image_default"];}];

visualEffectView.effect = [UIVisualEffect qmui_effectWithThemeProvider:^UIVisualEffect * _Nonnull(__kindof QMUIThemeManager * _Nonnull manager, NSString * _Nullable identifier, NSObject<QDThemeProtocol> *theme) {    return [UIBlurEffect effectWithStyle:[identifier isEqualToString:@"Dark"] ? UIBlurEffectStyleDark : UIBlurEffectStyleLight];}];

通常來(lái)說(shuō),一個(gè)項(xiàng)目里的顏色、模糊效果一般都只有可枚舉的固定的幾個(gè),建議將這些顏色、模糊效果緩存起來(lái)(使用 static 變量,或者用一個(gè)單例去保存,可參考 QDThemeManager),這樣可以大大減少代碼量,也不需要去記住創(chuàng)建動(dòng)態(tài)對(duì)象的語(yǔ)法。

// 適當(dāng)做一些抽取,就可以減少大量的代碼
view.backgroundColor = UIColor.qd_backgroundColor;
layer.backgroundColor = UIColor.qd_separatorColor.CGColor;
visualEffectView.effect = UIVisualEffect.qd_standardBlurEffect;

到此大部分界面已經(jīng)可以兼容,而對(duì)于自定義的 View 組件,它們的自定義屬性需要在主題切換時(shí)被刷新,則可參照下方來(lái)注冊(cè)屬性給 QMUIThemeManager。

@implementation CustomView
- (instancetype)initWithFrame:(CGRect)frame {   
 if (self = [super initWithFrame:frame]) {        
// ...               
 // 將組件里的樣式定義為 property,然后通過(guò) qmui_registerThemeColorProperties: 注冊(cè)給 QMUIThemeManager,這樣當(dāng)主題發(fā)生變化時(shí),會(huì)遍歷整個(gè)界面的所有 view,重新設(shè)置被注冊(cè)的屬性        
[self qmui_registerThemeColorProperties:@[NSStringFromSelector(@selector(borderColor)),                                                  
NSStringFromSelector(@selector(contentImage)),        
NSStringFromSelector(@selector(backgroundEffect))]];   
 }    
return self;
}
@end

如果上述提供的功能仍未能滿(mǎn)足業(yè)務(wù)的需求,也可直接重寫(xiě)
UIView/UIViewController 的 qmui_themeDidChangeByManager:identifier:theme: 方法,在內(nèi)部寫(xiě)自己的邏輯。
至此整個(gè) App 的主題實(shí)現(xiàn)和 Dark Mode 兼容工作就全部完成了。
至于主題的切換,如果 App 只是兼容 iOS 13 Dark Mode,則不需要理會(huì)這一點(diǎn),如果 App 里有提供主動(dòng)切換主題的操作給用戶(hù),則可參照以下代碼:

QMUIThemeManager.sharedInstance.currentThemeIdentifier = @"Dark";
// 切換到名為 Dark 的主題// 或
QMUIThemeManager.sharedInstance.currentTheme = darkTheme;
// 切換到 darkTheme 主題對(duì)象
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容