類似文章挺多的,大家都說的非常好,我就是湊湊熱鬧......
應(yīng)用場(chǎng)景:
當(dāng)前界面的設(shè)置一個(gè)透明的navigationbar的背景,并且實(shí)現(xiàn)漸變顯示或隱藏的動(dòng)畫,二級(jí)界面的navigationbar的背景不透明,使用APP的主題背景色(例如:不透明且無毛玻璃效果);
實(shí)現(xiàn)效果:

實(shí)現(xiàn)思路:
將系統(tǒng)原有導(dǎo)航欄的背景設(shè)置為透明色,同時(shí)在每個(gè) ViewController 上添加一個(gè) View 或者 NavigationBar 來充當(dāng)我們實(shí)際看到的導(dǎo)航欄,每個(gè) ViewController 同樣只需要關(guān)心自身的樣式即可。
第一步:增加一個(gè)屬性
用于記錄對(duì)navigationbar背景色的引用,用于實(shí)現(xiàn)navigationbar背景色變換動(dòng)畫;
/**
記錄對(duì)navigationbar背景色的引用,用于實(shí)現(xiàn)背景色變換動(dòng)畫;
*/
@property (nonatomic, strong) UIView *navigationBarBgViewRef;
第二步:在viewDidLoad中加入代碼:
(1)打開navigationbar的背景毛玻璃效果;
(2)設(shè)置navigationbar的背景為一張透明圖片;
(3)在self.view中添加一張模擬出來的navigaionbar的背景圖片;
/**
不使用navigationbar自帶的背景顏色,
而是使用自己模擬的navigationbar背景色
*/
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.navigationBarBgViewRef = [self appendSimulatorNavigationBarBgViewWithColor:COLOR_THEME];
第三步:在viewWillApear中加入代碼:
因?yàn)樵诒窘缑娴亩?jí)界面中可能會(huì)修改navigationbar的樣式,所以當(dāng)回到本界面時(shí),要恢復(fù)到本界面應(yīng)當(dāng)顯示的效果;
(1)打開navigationbar的背景毛玻璃效果;
(2)設(shè)置navigationbar的背景為一張透明圖片;
self.navigationController.navigationBar.translucent = YES;
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.navigationBarBgViewRef.alpha = 0;
補(bǔ)充相關(guān)代碼
#define WIDTH_SCREEN [[UIScreen mainScreen] bounds].size.width //屏幕寬度
#define HEIGHT_SCREEN [[UIScreen mainScreen] bounds].size.height //屏幕高度
#define IS_IPHONE_X (WIDTH_SCREEN == 375.f && HEIGHT_SCREEN == 812.f ? YES : NO)
#define IS_IPHONE_XSMAX (WIDTH_SCREEN == 414.f && HEIGHT_SCREEN == 896.f ? YES : NO)
#define HEIGHT_STATUSBAR (IS_IPHONE_X || IS_IPHONE_XSMAX ? 44.f : 20.f)
#define HEIGHT_NAVIGATION_BAR 44
- (UIView *)appendSimulatorNavigationBarBgViewWithColor:(UIColor *)color {
NSInteger simulatorBgViewTag = -9834534;//該值是胡亂定義的,就是個(gè)tag而已
if([self.view viewWithTag:simulatorBgViewTag]){
UIView *simulatorView = [self.view viewWithTag:simulatorBgViewTag];
[simulatorView removeFromSuperview];
}
CGFloat height = HEIGHT_NAVIGATION_BAR + HEIGHT_STATUSBAR;
CGSize size = CGSizeMake(WIDTH_SCREEN, height);
UIImage *imgNavBg = [UIImage imageWithColor:color size:size];
UIImageView *imgview = [[UIImageView alloc] initWithImage:imgNavBg];
imgview.contentMode = UIViewContentModeScaleToFill;
imgview.frame = CGRectMake(0, -1 * height, WIDTH_SCREEN,height);
imgview.tag = simulatorBgViewTag;//胡亂輸入的
[self.view addSubview:imgview];
return imgview;
}
在界面切換時(shí),實(shí)現(xiàn)navigationbar轉(zhuǎn)場(chǎng)變換效果有三種方法,在美團(tuán)《iOS系統(tǒng)中導(dǎo)航欄的轉(zhuǎn)場(chǎng)解決方案與最佳實(shí)踐》中有很詳細(xì)的描述,這里僅摘抄部分,本文中提到的方案其實(shí)就是美團(tuán)這篇文章中說到的方案二,文章的鏈接如下:
https://tech.meituan.com/navigation_transition_solution_and_best_practice_in_meituan.html
常見的解決方案如下所示:【摘抄自美團(tuán)思琦《iOS系統(tǒng)中導(dǎo)航欄的轉(zhuǎn)場(chǎng)解決方案與最佳實(shí)踐》】
-
重新實(shí)現(xiàn)一個(gè)類似 UINavigationController 的容器類視圖管理器,這個(gè)容器類視圖管理器做好不同 ViewController 間的導(dǎo)航欄樣式轉(zhuǎn)換工作,而每個(gè) ViewController 只需要關(guān)心自身的樣式即可。
19常見的導(dǎo)航欄轉(zhuǎn)場(chǎng)方案1示例圖 -
將系統(tǒng)原有導(dǎo)航欄的背景設(shè)置為透明色,同時(shí)在每個(gè) ViewController 上添加一個(gè) View 或者 NavigationBar 來充當(dāng)我們實(shí)際看到的導(dǎo)航欄,每個(gè) ViewController 同樣只需要關(guān)心自身的樣式即可。
20常見的導(dǎo)航欄轉(zhuǎn)場(chǎng)方案2示例圖 -
在轉(zhuǎn)場(chǎng)的過程中隱藏原有的導(dǎo)航欄并添加假的 NavigationBar,當(dāng)轉(zhuǎn)場(chǎng)結(jié)束后刪除假的 NavigationBar 并恢復(fù)原有的導(dǎo)航欄,這一過程可以通過 Swizzle 的方式完成,而每個(gè) ViewController 只需要關(guān)心自身的樣式即可。
21常見的導(dǎo)航欄轉(zhuǎn)場(chǎng)方案3示例圖
這三種方案各有優(yōu)劣,我們?cè)诰W(wǎng)上也可以看到很多關(guān)于它們的討論。
例如方案一,雖然看起來工作量大且難度高,但是這個(gè)工作一旦完成,我們就會(huì)將處理導(dǎo)航欄轉(zhuǎn)場(chǎng)的主動(dòng)權(quán)牢牢抓在手里。但這個(gè)方案的一個(gè)弊端就是,如果蘋果修改了導(dǎo)航欄的整體風(fēng)格,就好比 iOS 11 的大標(biāo)題特效,那么工作量就來了。
對(duì)于方案二而言,雖然看起來簡(jiǎn)單易用,但這需要一個(gè)良好的繼承關(guān)系,如果整個(gè)工程里的繼承關(guān)系混亂或者是歷史包袱比較重,后續(xù)的維護(hù)就像“打補(bǔ)丁”一樣,另外這個(gè)方案也需要良好的團(tuán)隊(duì)代碼規(guī)范和完善的技術(shù)文檔來做輔助。
對(duì)于方案三而言,它不需要所謂的繼承關(guān)系,使用起來也相對(duì)簡(jiǎn)單,這對(duì)于那些繼承關(guān)系和歷史包袱比較重的工程而言,這一個(gè)不錯(cuò)的解決方案,但在解決 Bug 的時(shí)候,Swizzle 這種方式無疑會(huì)增加解決問題的時(shí)間成本和學(xué)習(xí)成本。


