0招驴、前言
隨著iOS13的普及腹鹉,大多數(shù)的APP都已經(jīng)適配了暗黑模式棺蛛,網(wǎng)絡(luò)上關(guān)于暗黑模式適配的文章也很多,基本看幾篇就能解決掉iOS13暗黑模式的適配。我看了大部分的文章哩俭,基本都是對(duì)暗黑模式通用的介紹和適配绞蹦,一些實(shí)際項(xiàng)目中的具體細(xì)節(jié)卻很少提及,所以此篇文章算是對(duì)于其他暗黑模式適配的補(bǔ)充终畅,力求能做到完美適配暗黑模式籍胯。PS:如果你沒(méi)看過(guò)其他的暗黑模式適配文章,那么你在看此文章前需要先去看一下其他關(guān)于暗黑模式適配的文章离福,此文章默認(rèn)你是已經(jīng)知道暗黑模式需要怎么適配了的杖狼。
1、LaunchScreen.storyboard
某些APP雖然適配了暗黑模式妖爷,但是對(duì)于啟動(dòng)頁(yè)卻沒(méi)有進(jìn)行適配蝶涩。試想一下,當(dāng)你使用暗黑模式在晚上打開(kāi)APP的時(shí)候絮识,本來(lái)其他的都是深色的突然被啟動(dòng)頁(yè)的白色背景圖片或者亮色背景閃了幾下绿聘,眼睛會(huì)不會(huì)覺(jué)得難受。所以次舌,建議大家如果你們的APP是亮色背景的話斜友,那么建議你適配暗黑模式的時(shí)候也要考慮一下對(duì)啟動(dòng)圖進(jìn)行適配。為什么我在這里不說(shuō)launchImage呢垃它,因?yàn)楦鶕?jù)蘋(píng)果的規(guī)定鲜屏,2020年4月份的時(shí)候所有的APP必須使用LaunchScreen才能提交APP,所以国拇,現(xiàn)在適配的時(shí)候盡快替換成LaunchScreen洛史。LaunchScreen適配暗黑模式也挺簡(jiǎn)單的,只需要點(diǎn)擊下面的模式進(jìn)行切換就能行酱吝。
需要注意的是:當(dāng)你由launchImage換成LaunchScreen以后也殖,或者是已經(jīng)適配了暗黑模式但是就是看不到效果的時(shí)候,這是正常的,因?yàn)閱?dòng)圖被緩存了忆嗜,這時(shí)候卸載APP在試試己儒,如果還是不行,那么多卸載幾次試試捆毫,或者換臺(tái)手機(jī)試試闪湾,一定要相信自己。我在適配這個(gè)的時(shí)候就出現(xiàn)了一直不行绩卤,然后我以為是不能這樣適配途样,后面用另外一臺(tái)沒(méi)有安裝過(guò)APP的手機(jī)就可以顯示出來(lái)。PS:我沒(méi)有試過(guò)在Assets里面弄暗黑模式的和正常模式的圖片濒憋,然后在LaunchScreen放一張圖片的方式何暇,因?yàn)槲议_(kāi)始這樣弄,但是由于緩存的原因一直沒(méi)出來(lái)凛驮,我以為這樣不行裆站,所以換成點(diǎn)擊下面的style設(shè)置去了。大家可以試試直接像其他圖片適配一樣進(jìn)行適配可不可行黔夭。
2宏胯、WKWebview適配
現(xiàn)在大部分需要注冊(cè)登錄的APP都有一個(gè)隱私協(xié)議,而這個(gè)網(wǎng)頁(yè)通常是使用WKWebview進(jìn)行加載的(說(shuō)到這里在提醒大家一下:webview也被廢棄了纠修,所以大家快轉(zhuǎn)換到WKWebview上來(lái))胳嘲。這時(shí)候如果大家能叫前端幫忙適配,那肯定非常省事了扣草。但是如果需要自己進(jìn)行適配了牛,那么也是可以的。核心就是通過(guò)JS代碼去動(dòng)態(tài)的修改HTML的背景色辰妙。先上代碼在進(jìn)行解釋:
#import "ViewController.h"
#import <WebKit/WebKit.h>
@interface ViewController ()<WKNavigationDelegate>
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self loadHtmlWithWKView];
}
-(void)loadHtmlWithWKView{
WKWebViewConfiguration *wkWebconfigura = [[WKWebViewConfiguration alloc]init];
WKWebView *wkView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:wkWebconfigura];
[wkView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://juejin.im/welcome/ios"]]];
wkView.navigationDelegate = self;
self.webView = wkView;
[self.view addSubview:wkView];
self.webView.hidden = YES;
}
//navigationDelegate 當(dāng)網(wǎng)頁(yè)加載完畢后會(huì)調(diào)用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
NSString *backgroundColor = @"";
NSString *labelColor = @"";
if (@available(iOS 13.0, *)) {
if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
backgroundColor = @"\"#001A1A\"";
labelColor = @"'#FF0000'";
}else{
backgroundColor = @"\"#FFFFFF\"";
labelColor = @"'#666666'";
}
} else {
self.webView.hidden = NO;
return;
}
//寫(xiě)入JS代碼
[self.webView evaluateJavaScript:[NSString stringWithFormat:@"document.body.style.backgroundColor=%@",backgroundColor] completionHandler:nil];
[self.webView evaluateJavaScript:[NSString stringWithFormat:@"document.getElementsByTagName('body')[0].style.webkitTextFillColor=%@",labelColor] completionHandler:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.webView.hidden = NO;
});
}
@end
核心思想就是通過(guò)JS代碼去動(dòng)態(tài)的修改網(wǎng)頁(yè)的背景顏色和文字顏色鹰祸。在webView:(WKWebView *)webView didFinishNavigation的時(shí)候進(jìn)行當(dāng)前模式的判斷,在通過(guò)JS代碼進(jìn)行修改網(wǎng)頁(yè)的顏色密浑。有人可能會(huì)問(wèn)蛙婴,為什么不用WKUserScript去進(jìn)行設(shè)置了,我試過(guò)了尔破,不起作用街图。用下面的同一句代碼進(jìn)行設(shè)置,沒(méi)有任何反應(yīng)懒构,我以為是因?yàn)楹蠹虞d的網(wǎng)頁(yè)覆蓋掉了之前設(shè)置的背景顏色餐济,說(shuō)以在開(kāi)始的JS代碼里面加入了!important,結(jié)果也是不行的。為什么先對(duì)webView進(jìn)行隱藏呢胆剧,這是因?yàn)槲业腁PP隱私協(xié)議的背景顏色默認(rèn)就是白色的絮姆,所以加載的時(shí)候會(huì)先顯示白色,然后馬上閃到我設(shè)置的顏色,對(duì)于用戶來(lái)說(shuō)篙悯,體驗(yàn)不是很好蚁阳,所以先進(jìn)行隱藏,而進(jìn)行0.5s的延時(shí)在顯示是因?yàn)槟菚r(shí)候還沒(méi)設(shè)置完鸽照,所以有時(shí)候會(huì)出現(xiàn)沒(méi)改過(guò)來(lái)螺捐,或者是也會(huì)出現(xiàn)閃現(xiàn)的情況。下面看下效果:
修改成功移宅,但是由于示例的li也是有背景顏色的归粉,而我們修改的是body的背景椿疗,所以會(huì)有白色的cell漏峰。可以看到勾選swift/flutter的背景就是我們?cè)O(shè)置的背景届榄,而我們的隱私協(xié)議一般都是P標(biāo)簽組成的浅乔,所以如果你的隱私協(xié)議修改body的背景不成功的話可以具體針對(duì)你的具體需求進(jìn)行修改。
3輪播圖(網(wǎng)絡(luò)圖片)的適配
對(duì)于圖片的適配铝条,大多數(shù)的做法是準(zhǔn)備兩張圖片靖苇,一張是暗黑模式的,一張是正常模式的班缰。但是對(duì)于網(wǎng)絡(luò)上(公司服務(wù)器)拿到的輪播圖或者網(wǎng)絡(luò)圖片贤壁,這些要用兩張的話個(gè)人覺(jué)得有點(diǎn)麻煩了,如果是公司的圖片UI需要準(zhǔn)備兩張倒是可以實(shí)現(xiàn)埠忘,但是如果是一些其他的圖片脾拆,譬如用戶自己上傳的圖片,那么我們是無(wú)法進(jìn)行修改的莹妒。所以我的做法也很簡(jiǎn)單名船,在原來(lái)的imageView上面加蓋一個(gè)蒙版就行,當(dāng)用戶切換到暗黑模式的時(shí)候把蒙版打開(kāi)旨怠,這樣可以調(diào)低圖片的亮度值渠驼,假如是一張亮色的圖片,因?yàn)橛辛嗣砂嬉膊粫?huì)至于那么刺眼鉴腻。上代碼:(由于對(duì)比顯示迷扇,所以我沒(méi)有用圖片直接設(shè)置imageView的背景為紅色)
UIImageView *imageView = [[UIImageView alloc] init];
imageView.backgroundColor = [UIColor redColor];
imageView.frame = CGRectMake(0, 100, self.view.frame.size.width, 300);
[self.view addSubview:imageView];
UIView *backView = [[UIView alloc] init];
backView.frame = imageView.frame;
backView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
[self.view addSubview:backView];
這樣一對(duì)比就會(huì)發(fā)現(xiàn)加了蒙版的視覺(jué)效果不會(huì)那么刺眼,我的透明度設(shè)置的是0.5爽哎,你可以根據(jù)你們公司的需求進(jìn)行設(shè)置即可蜓席。這樣的話也算是完成了網(wǎng)絡(luò)圖片或者輪播圖的暗黑模式適配了,
BUT:因?yàn)槟慵恿嗣砂婢肭啵匀绻愫竺娴膙iew或者是imageView有手勢(shì)的話會(huì)失效
所以我們需要對(duì)點(diǎn)擊到蒙版上的這個(gè)事件進(jìn)行傳遞瓮床,詳細(xì)的相關(guān)資料大家可以自行去搜索。我只告訴你最簡(jiǎn)單的解決方法,可能會(huì)有不嚴(yán)謹(jǐn)?shù)牡胤桨_@時(shí)候我們只需要自定義一個(gè)view踢步,然后在hitTest:(CGPoint)point withEvent:(UIEvent *)event里面讓當(dāng)前的這個(gè)蒙版view不響應(yīng)手勢(shì)即可。
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
UIView *view = [super hitTest:point withEvent:event];
if (view== self) {
return nil;
}
return [super hitTest:point withEvent:event];
}
本文只是默認(rèn)了當(dāng)前用戶是在暗黑模式下的丑掺,實(shí)際開(kāi)發(fā)中大家還需要用戶在當(dāng)前頁(yè)面切換了模式获印,這個(gè)時(shí)候就需要在具體的界面監(jiān)聽(tīng)下面這個(gè)方法
-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection{
//注意:這里返回的是前一次的狀態(tài)
[super traitCollectionDidChange:previousTraitCollection];
if (@available(iOS 13.0, *)) {
if (previousTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
self.backView.hidden = YES;
}else if (previousTraitCollection.userInterfaceStyle == UIUserInterfaceStyleLight){
self.backView.hidden = NO;
}
} else {
self.backView.hidden = YES;
}
}
但是需要注意的是這個(gè)方法顯示的是前一次的狀態(tài)。
至此街州,本文提到的關(guān)于暗黑模式的適配全部完成兼丰,有了這些以后,整個(gè)APP才算得上是完全適配了暗黑模式吧唆缴,而不是有一部分是深色的鳍征,有些地方卻又是亮色的。