一、在項(xiàng)目開發(fā)中NavigationBar設(shè)置遇到的坑
在平時的開發(fā)中,我們往往會遇到這樣的需求,兩個ViewController的NavigationBar顏色不同、透明度不同或者有的隱藏有的不隱藏,當(dāng)兩個ViewController進(jìn)行push或pop操作時,那么你可能會看到下面現(xiàn)象:
-
兩個ViewController的NavigationBar顏色不同,push/pop時顏色切換不和諧。
push/pop顏色切換不和諧 -
兩個ViewController的NavigationBar隱藏設(shè)置不一樣,push/pop時隱藏NavigationBar切換不和諧。
push/pop時隱藏NavigationBar切換不和諧
很丑有木有O(≧口≦)O,強(qiáng)迫癥接受不了有木有O(≧口≦)O。
導(dǎo)致出現(xiàn)上述問題的原因是navigationBar只有一個,改變navigationBar樣式一定會影響其他ViewController的顯示。
二、尋找解決方案
隱藏與顯示的bug解決比較簡單,因?yàn)樘O果已經(jīng)做好了,出現(xiàn)上述問題的原因是,沒有使用對的方法。
隱藏NavigationBar蘋果提供了兩個方法:[navigationController setNavigationBarHidden:]和[navigationController setNavigationBarHidden:animated:]。第一個方法無動畫隱藏navigationBar,第二個方法可以控制是否動畫隱藏navigationBar。解決上述bug只需如下代碼:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:animated];
//不要使用下面方法,下面方法會導(dǎo)致隱藏和不隱藏的viewController轉(zhuǎn)場時出現(xiàn)bug
// [self.navigationController setNavigationBarHidden:NO];
}
OK,隱藏與顯示的bug解決了。效果如下:

下面解決顏色的問題。在很多的APP都可以看到不同顏色的navigationBar的轉(zhuǎn)場,但這些APP都完美的解決了顏色問題,比如微信。所以就要看看微信是如何處理的呢,這個時候就用到了一個款神奇,Mac軟件Reveal,它可以看到在手機(jī)中安裝的APP頁面層級,至于如何使用請移步:使用Reveal查看任意App的技巧。
通過Reveal看到了微信的頁面層次,如下圖

觀察微信的層級發(fā)現(xiàn),微信的navigationBar是透明的,ViewController頂部有一個view來充當(dāng)navigationBar背景色,如上圖左右兩邊的發(fā)現(xiàn)ViewController和小程序ViewController的頂部都有一個view,左邊是黑字的右邊是白色的,這樣每個viewController的navigationBar的背景色就可以單獨(dú)設(shè)置。
三、有了指導(dǎo)方向,開始動手搬磚
解決方法好像很簡單,只需要在viewController.view的頂部加上一個barBgView就可以了(內(nèi)心暗喜:這種代碼我兩分鐘就可以敲完,啊哈哈哈ψ(`?′)ψ)。
那么開始戰(zhàn)斗吧,啊哈哈! 哈利路亞!德瑪西亞!賜給我碼神的力量吧ヽ(`Д′)?ヽ(`Д′)?ヽ(`Д′)?!
戰(zhàn)斗沒開始就發(fā)現(xiàn)遇到了坑,難道我要每個viewController里都寫一遍加入barBgView的代碼?不行viewController太多寫起來太累;那寫一個繼承自viewController的父類,然后讓所有viewController繼承父類,不行那樣還是每個viewController都要改;有沒有讓新項(xiàng)目改動極少的代碼就可以實(shí)現(xiàn)的方法呢?答案是有的,只需要Category和黑科技Method Swizzling即可。
首先建兩個UIViewController的Category.
第一個為UIViewController+CFYNavigationBarTransition.h
// UIViewController CFYNavigationBarTransition
@interface UIViewController (CFYNavigationBarTransition)
/**
設(shè)置導(dǎo)航欄是否隱藏
@param hidden 隱藏
@param animated 動畫
*/
- (void)cfy_setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;
@end
第二個位UINavigationController+CFYNavigationBarTransition_Public.h
@interface UIViewController (CFYNavigationBarTransition_Public)
/**
設(shè)置導(dǎo)航欄背景色
@param color 背景色
*/
- (void)cfy_setNavigationBarBackgroundColor:(UIColor *)color;
/**
設(shè)置背景圖片
@param image 背景圖
*/
- (void)cfy_setNavigationBarBackgroundImage:(UIImage *)image;
/**
設(shè)置導(dǎo)航欄透明度
@param alpha 透明度
*/
- (void)cfy_setNavigationBarAlpha:(CGFloat)alpha;
/**
bar背景色
*/
@property (readonly) UIColor *cfy_navigationBarBackgroundColor;
/**
bar透明度
*/
@property (readonly) CGFloat cfy_navigationBarAlpha;
@end
兩個都是UIViewController的Category,以public結(jié)尾的文件中是對外提供公開的方法和屬性,也就是用戶可以使用的方法和屬性,另個則是放私有方法和屬性。
兩個category中方法和屬性的實(shí)現(xiàn)都在UIViewController+CFYNavigationBarTransition.m中實(shí)現(xiàn),實(shí)現(xiàn)邏輯加在了注釋中
@interface UIViewController ()
/**
cfy_navBarBgView,這個view就是核心,改變navigationBar顏色其實(shí)是改變cfy_navBarBgView的背景色
*/
@property (nonatomic, strong) UIView *cfy_navBarBgView;
/**
用來判斷view是否加載
*/
@property (nonatomic, assign) BOOL cfy_viewAppeared;
/**
保存navigationBar顏色
*/
@property (nonatomic, strong) UIColor *cfy_navigationBarBackgroundColor;
/**
保存navigationBar顏色透明度
*/
@property (nonatomic, assign) CGFloat cfy_navigationBarAlpha;
@end
@implementation UIViewController (CFYNavigationBarTransition)
/**
在load中,swizzle四個方法viewDidLoad、viewWillLayoutSubviews、viewDidAppear:、viewDidDisappear:。
*/
+(void)load {
CFYSwizzleMethod(self, @selector(viewDidLoad), @selector(cfy_viewDidLoad));
CFYSwizzleMethod(self, @selector(viewWillLayoutSubviews), @selector(cfy_viewWillLayoutSubviews));
CFYSwizzleMethod(self, @selector(viewDidAppear:), @selector(cfy_viewDidAppear:));
CFYSwizzleMethod(self, @selector(viewDidDisappear:), @selector(cfy_viewDidDisappear:));
}
/**
在viewDidLoad中添加cfy_navBarBgView
*/
- (void)cfy_viewDidLoad {
[self cfy_viewDidLoad];
// 如果存在navigationController則添加cfy_navBarBgView
if (self.navigationController) {
[self cfy_addNavBarBgView];
}
}
- (void)cfy_viewDidAppear:(BOOL)animated {
[self cfy_viewDidAppear:animated];
self.cfy_viewAppeared = YES;
}
- (void)cfy_viewDidDisappear:(BOOL)animated {
[self cfy_viewDidDisappear:YES];
self.cfy_viewAppeared = NO;
}
/**
在viewWillLayoutSubviews中對cfy_navBarBgView進(jìn)行處理,使cfy_navBarBgView能在不同環(huán)境正確顯示
*/
- (void)cfy_viewWillLayoutSubviews {
[self cfy_viewWillLayoutSubviews];
// 當(dāng)前viewController沒navigationController,直接退出
if (!self.navigationController) {
return;
}
/**
self.navigationController.navigationBar隱藏了,做一些處理。
如果在navigationBar隱藏時,旋轉(zhuǎn)屏幕,這時如果不處理后并return,而是走下面的代碼,那么并不能正確的獲取到cfy_navBarBgView的frame。
所以在這里直接將cfy_navBarBgView的寬度設(shè)置成屏幕看度,其他不變保持cfy_navBarBgView在隱藏前的狀態(tài),這樣在從豎屏切換到橫屏顯示時不會出現(xiàn)一些視覺上的bug
*/
if (self.navigationController.navigationBar.hidden) {
CGRect rect = self.cfy_navBarBgView.frame;
self.cfy_navBarBgView.frame = CGRectMake(0, rect.origin.y, CFYScreenWidth, rect.size.height);
return;
}
// 獲取navigationBar的backgroundView
UIView *backgroundView = [self.navigationController.navigationBar valueForKey:@"_backgroundView"];
// 如果沒有則return
if (!backgroundView) {
return;
}
// 獲取navigationBar的backgroundView在self.view中的位置,這個位置也就是cfy_navBarBgView所在的位置。
CGRect rect = [backgroundView.superview convertRect:backgroundView.frame toView:self.view];
// 出現(xiàn)rect.origin.x < 0,情況只有在頁面剛push出來并且navigationBar隱藏的時候。
// 這個時候講rect.origin.y上移rect.size.height,使cfy_navBarBgView也隱藏
// 目的是防止在navigationBar.hidden=NO時出現(xiàn)動畫顯示錯誤
if (rect.origin.x < 0) {
rect.origin.y = 0 - rect.size.height;
}
// cfy_navBarBgView的x固定0
self.cfy_navBarBgView.frame = CGRectMake(0, rect.origin.y, rect.size.width, rect.size.height);
// 設(shè)置當(dāng)前view的clipsToBounds = NO,原因是,self.view.top可能是從navigationBar.bottom開始,如果clipsToBounds = YES,則cfy_navBarBgView無法顯示
self.view.clipsToBounds = NO;
// 將cfy_navBarBgView移到self.view最頂端,防止被其他view遮蓋
[self.view bringSubviewToFront:self.cfy_navBarBgView];
}
#pragma mark - 公開方法 -
/**
設(shè)置導(dǎo)航欄背景色
@param color 背景色
*/
- (void)cfy_setNavigationBarBackgroundColor:(UIColor *)color {
self.cfy_navigationBarBackgroundColor = color;
if (self.navigationController) {
self.cfy_navBarBgView.backgroundColor = color;
}
}
/**
設(shè)置背景圖片
@param image 背景圖
*/
- (void)cfy_setNavigationBarBackgroundImage:(UIImage *)image {
// 后續(xù)版本加入
}
/**
設(shè)置導(dǎo)航欄透明度
@param alpha 透明度
*/
- (void)cfy_setNavigationBarAlpha:(CGFloat)alpha {
self.cfy_navigationBarAlpha = alpha;
if (self.navigationController) {
self.cfy_navBarBgView.alpha = alpha;
}
}
#pragma mark - 私有方法 -
/**
設(shè)置導(dǎo)航欄是否隱藏
@param hidden 隱藏
@param animated 動畫
*/
- (void)cfy_setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {
if (self.navigationController) {
// 這里只在cfy_navBarBgView隱藏時使用了動畫,原因是cfy_navBarBgView顯示時系統(tǒng)自動給加上了動畫(這很神奇)
if (hidden && self.cfy_viewAppeared && animated && !self.navigationController.navigationBar.hidden) {
// 在cfy_navBarBgView隱藏,并且view已經(jīng)Appeared,并且有動畫,并且navigationBar不是已經(jīng)隱藏了時就進(jìn)行動畫
CGRect rect = self.cfy_navBarBgView.frame;
[UIView animateWithDuration:0.2 animations:^{
// 動畫時向上運(yùn)動
self.cfy_navBarBgView.frame = CGRectMake(0, rect.origin.y - rect.size.height, rect.size.width, rect.size.height);
} completion:^(BOOL finished) {
// 動畫完成后cfy_navBarBgView隱藏
self.cfy_navBarBgView.hidden = hidden;
}];
} else {
self.cfy_navBarBgView.hidden = hidden;
}
}
}
/**
添加navigationBar背景view
*/
- (void)cfy_addNavBarBgView {
if (!self.isViewLoaded) {
return;
}
if (!self.navigationController) {
return;
}
if (!self.navigationController.navigationBar) {
return;
}
// 獲取NavigationBar的BackgroundView在當(dāng)前view中的位置
CGRect rect = [self cfy_getNavigationBarBackgroundViewRect];
// 初始化
UIView *navBarBgView = [[UIView alloc] initWithFrame:CGRectMake(0, rect.origin.y, rect.size.width, rect.size.height)];
[self.view addSubview:navBarBgView];
// 判斷有沒有設(shè)置顏色
if (self.cfy_navigationBarBackgroundColor) {
navBarBgView.backgroundColor = self.cfy_navigationBarBackgroundColor;
} else {
// 默認(rèn)是白色
navBarBgView.backgroundColor = [UIColor whiteColor];
self.cfy_navigationBarBackgroundColor = [UIColor whiteColor];
}
// 設(shè)置透明度,默認(rèn)為1
navBarBgView.alpha = self.cfy_navigationBarAlpha;
// 是否隱藏
navBarBgView.hidden = self.navigationController.navigationBar.isHidden;
// 保存
[self setCfy_navBarBgView:navBarBgView];
}
/**
獲取navigationBar._backgroundView在self.view中的frame
@return _backgroundView的frame
*/
- (CGRect)cfy_getNavigationBarBackgroundViewRect {
UIView *backgroundView = [self.navigationController.navigationBar valueForKey:@"_backgroundView"];
if (!backgroundView) {
return CGRectZero;
}
CGRect rect = [backgroundView.superview convertRect:backgroundView.frame toView:self.view];
return rect;
}
#pragma mark - getter/setter -
-(UIView *)cfy_navBarBgView {
UIView *navBarBgView = objc_getAssociatedObject(self, _cmd);
if (nil == navBarBgView) {
[self cfy_addNavBarBgView];
}
return navBarBgView;
}
- (void)setCfy_navBarBgView:(UIView *)navBarBgView {
objc_setAssociatedObject(self, @selector(cfy_navBarBgView), navBarBgView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)cfy_viewAppeared {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setCfy_viewAppeared:(BOOL)viewAppeared {
objc_setAssociatedObject(self, @selector(cfy_viewAppeared), @(viewAppeared), OBJC_ASSOCIATION_ASSIGN);
}
- (UIColor *)cfy_navigationBarBackgroundColor {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setCfy_navigationBarBackgroundColor:(UIColor *)navigationBarBackgroundColor {
objc_setAssociatedObject(self, @selector(cfy_navigationBarBackgroundColor), navigationBarBackgroundColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(CGFloat)cfy_navigationBarAlpha {
NSNumber *alpha = objc_getAssociatedObject(self, _cmd);
if (!alpha) {
[self setCfy_navigationBarAlpha:1.];
return 1.;
}
return [alpha floatValue];
}
- (void)setCfy_navigationBarAlpha:(CGFloat)navigationBarAlpha {
objc_setAssociatedObject(self, @selector(cfy_navigationBarAlpha), @(navigationBarAlpha), OBJC_ASSOCIATION_ASSIGN);
}
@end
OK,主要功能完成,上面代碼中還有幾個問題:
- 問題1:在設(shè)置[navigationController setNavigationBarHidden:animated:]和[navigationController setNavigationBarHidden:]方法是應(yīng)該對cfy_navBarBgView進(jìn)行操作;
- 問題2:沒有設(shè)置NavigationBar為透明,不設(shè)置成透明,前面的工作都白做了。
那么對navigationController也建一個Category,并swizzle需要的方法。代碼如下:
UIViewController+CFYNavigationBarTransition.m
@interface UIViewController ()
/**
cfy_navBarBgView,這個view就是核心,改變navigationBar顏色其實(shí)是改變cfy_navBarBgView的背景色
*/
@property (nonatomic, strong) UIView *cfy_navBarBgView;
/**
用來判斷view是否加載
*/
@property (nonatomic, assign) BOOL cfy_viewAppeared;
/**
保存navigationBar顏色
*/
@property (nonatomic, strong) UIColor *cfy_navigationBarBackgroundColor;
/**
保存navigationBar顏色透明度
*/
@property (nonatomic, assign) CGFloat cfy_navigationBarAlpha;
@end
@implementation UIViewController (CFYNavigationBarTransition)
/**
在load中,swizzle四個方法viewDidLoad、viewWillLayoutSubviews、viewDidAppear:、viewDidDisappear:。
*/
+(void)load {
CFYSwizzleMethod(self, @selector(viewDidLoad), @selector(cfy_viewDidLoad));
CFYSwizzleMethod(self, @selector(viewWillLayoutSubviews), @selector(cfy_viewWillLayoutSubviews));
CFYSwizzleMethod(self, @selector(viewDidAppear:), @selector(cfy_viewDidAppear:));
CFYSwizzleMethod(self, @selector(viewDidDisappear:), @selector(cfy_viewDidDisappear:));
}
/**
在viewDidLoad中添加cfy_navBarBgView
*/
- (void)cfy_viewDidLoad {
[self cfy_viewDidLoad];
// 如果存在navigationController則添加cfy_navBarBgView
if (self.navigationController) {
[self cfy_addNavBarBgView];
}
}
- (void)cfy_viewDidAppear:(BOOL)animated {
[self cfy_viewDidAppear:animated];
self.cfy_viewAppeared = YES;
}
- (void)cfy_viewDidDisappear:(BOOL)animated {
[self cfy_viewDidDisappear:YES];
self.cfy_viewAppeared = NO;
}
/**
在viewWillLayoutSubviews中對cfy_navBarBgView進(jìn)行處理,使cfy_navBarBgView能在不同環(huán)境正確顯示
*/
- (void)cfy_viewWillLayoutSubviews {
[self cfy_viewWillLayoutSubviews];
// 當(dāng)前viewController沒navigationController,直接退出
if (!self.navigationController) {
return;
}
/**
self.navigationController.navigationBar隱藏了,做一些處理。
如果在navigationBar隱藏時,旋轉(zhuǎn)屏幕,這時如果不處理后并return,而是走下面的代碼,那么并不能正確的獲取到cfy_navBarBgView的frame。
所以在這里直接將cfy_navBarBgView的寬度設(shè)置成屏幕看度,其他不變保持cfy_navBarBgView在隱藏前的狀態(tài),這樣在從豎屏切換到橫屏顯示時不會出現(xiàn)一些視覺上的bug
*/
if (self.navigationController.navigationBar.hidden) {
CGRect rect = self.cfy_navBarBgView.frame;
self.cfy_navBarBgView.frame = CGRectMake(0, rect.origin.y, CFYScreenWidth, rect.size.height);
return;
}
// 獲取navigationBar的backgroundView
UIView *backgroundView = [self.navigationController.navigationBar valueForKey:@"_backgroundView"];
// 如果沒有則return
if (!backgroundView) {
return;
}
// 獲取navigationBar的backgroundView在self.view中的位置,這個位置也就是cfy_navBarBgView所在的位置。
CGRect rect = [backgroundView.superview convertRect:backgroundView.frame toView:self.view];
// 出現(xiàn)rect.origin.x < 0,情況只有在頁面剛push出來并且navigationBar隱藏的時候。
// 這個時候講rect.origin.y上移rect.size.height,使cfy_navBarBgView也隱藏
// 目的是防止在navigationBar.hidden=NO時出現(xiàn)動畫顯示錯誤
if (rect.origin.x < 0) {
rect.origin.y = 0 - rect.size.height;
}
// cfy_navBarBgView的x固定0
self.cfy_navBarBgView.frame = CGRectMake(0, rect.origin.y, rect.size.width, rect.size.height);
// 設(shè)置當(dāng)前view的clipsToBounds = NO,原因是,self.view.top可能是從navigationBar.bottom開始,如果clipsToBounds = YES,則cfy_navBarBgView無法顯示
self.view.clipsToBounds = NO;
// 將cfy_navBarBgView移到self.view最頂端,防止被其他view遮蓋
[self.view bringSubviewToFront:self.cfy_navBarBgView];
}
#pragma mark - 公開方法 -
/**
設(shè)置導(dǎo)航欄背景色
@param color 背景色
*/
- (void)cfy_setNavigationBarBackgroundColor:(UIColor *)color {
self.cfy_navigationBarBackgroundColor = color;
if (self.navigationController) {
self.cfy_navBarBgView.backgroundColor = color;
}
}
/**
設(shè)置背景圖片
@param image 背景圖
*/
- (void)cfy_setNavigationBarBackgroundImage:(UIImage *)image {
// 后續(xù)版本加入
}
/**
設(shè)置導(dǎo)航欄透明度
@param alpha 透明度
*/
- (void)cfy_setNavigationBarAlpha:(CGFloat)alpha {
self.cfy_navigationBarAlpha = alpha;
if (self.navigationController) {
self.cfy_navBarBgView.alpha = alpha;
}
}
#pragma mark - 私有方法 -
/**
設(shè)置導(dǎo)航欄是否隱藏
@param hidden 隱藏
@param animated 動畫
*/
- (void)cfy_setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {
if (self.navigationController) {
// 這里只在cfy_navBarBgView隱藏時使用了動畫,原因是cfy_navBarBgView顯示時系統(tǒng)自動給加上了動畫(這很神奇)
if (hidden && self.cfy_viewAppeared && animated && !self.navigationController.navigationBar.hidden) {
// 在cfy_navBarBgView隱藏,并且view已經(jīng)Appeared,并且有動畫,并且navigationBar不是已經(jīng)隱藏了時就進(jìn)行動畫
CGRect rect = self.cfy_navBarBgView.frame;
[UIView animateWithDuration:0.2 animations:^{
// 動畫時向上運(yùn)動
self.cfy_navBarBgView.frame = CGRectMake(0, rect.origin.y - rect.size.height, rect.size.width, rect.size.height);
} completion:^(BOOL finished) {
// 動畫完成后cfy_navBarBgView隱藏
self.cfy_navBarBgView.hidden = hidden;
}];
} else {
self.cfy_navBarBgView.hidden = hidden;
}
}
}
/**
添加navigationBar背景view
*/
- (void)cfy_addNavBarBgView {
if (!self.isViewLoaded) {
return;
}
if (!self.navigationController) {
return;
}
if (!self.navigationController.navigationBar) {
return;
}
// 獲取NavigationBar的BackgroundView在當(dāng)前view中的位置
CGRect rect = [self cfy_getNavigationBarBackgroundViewRect];
// 初始化
UIView *navBarBgView = [[UIView alloc] initWithFrame:CGRectMake(0, rect.origin.y, rect.size.width, rect.size.height)];
[self.view addSubview:navBarBgView];
// 判斷有沒有設(shè)置顏色
if (self.cfy_navigationBarBackgroundColor) {
navBarBgView.backgroundColor = self.cfy_navigationBarBackgroundColor;
} else {
// 默認(rèn)是白色
navBarBgView.backgroundColor = [UIColor whiteColor];
self.cfy_navigationBarBackgroundColor = [UIColor whiteColor];
}
// 設(shè)置透明度,默認(rèn)為1
navBarBgView.alpha = self.cfy_navigationBarAlpha;
// 是否隱藏
navBarBgView.hidden = self.navigationController.navigationBar.isHidden;
// 保存
[self setCfy_navBarBgView:navBarBgView];
}
/**
獲取navigationBar._backgroundView在self.view中的frame
@return _backgroundView的frame
*/
- (CGRect)cfy_getNavigationBarBackgroundViewRect {
UIView *backgroundView = [self.navigationController.navigationBar valueForKey:@"_backgroundView"];
if (!backgroundView) {
return CGRectZero;
}
CGRect rect = [backgroundView.superview convertRect:backgroundView.frame toView:self.view];
return rect;
}
#pragma mark - getter/setter -
-(UIView *)cfy_navBarBgView {
UIView *navBarBgView = objc_getAssociatedObject(self, _cmd);
if (nil == navBarBgView) {
[self cfy_addNavBarBgView];
}
return navBarBgView;
}
- (void)setCfy_navBarBgView:(UIView *)navBarBgView {
objc_setAssociatedObject(self, @selector(cfy_navBarBgView), navBarBgView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)cfy_viewAppeared {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setCfy_viewAppeared:(BOOL)viewAppeared {
objc_setAssociatedObject(self, @selector(cfy_viewAppeared), @(viewAppeared), OBJC_ASSOCIATION_ASSIGN);
}
- (UIColor *)cfy_navigationBarBackgroundColor {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setCfy_navigationBarBackgroundColor:(UIColor *)navigationBarBackgroundColor {
objc_setAssociatedObject(self, @selector(cfy_navigationBarBackgroundColor), navigationBarBackgroundColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(CGFloat)cfy_navigationBarAlpha {
NSNumber *alpha = objc_getAssociatedObject(self, _cmd);
if (!alpha) {
[self setCfy_navigationBarAlpha:1.];
return 1.;
}
return [alpha floatValue];
}
- (void)setCfy_navigationBarAlpha:(CGFloat)navigationBarAlpha {
objc_setAssociatedObject(self, @selector(cfy_navigationBarAlpha), @(navigationBarAlpha), OBJC_ASSOCIATION_ASSIGN);
}
@end
至此所有的代碼完工。
- 改變navigationBar的顏色,調(diào)用[viewController cfy_setNavigationBarBackgroundColor:bgColor]方法。
- 改變navigationBar的透明度,調(diào)用[viewController cfy_setNavigationBarAlpha:alpha]方法.
- 隱藏則直接調(diào)用UINavigationController中設(shè)置NavigationBar隱藏的方法
注意事項(xiàng):不要設(shè)置NavigationBar的translucent為NO,原因是設(shè)置了translucent=NO,NavigationBar就不能透明了。
四、成果展示


五、代碼地址
GitHub: CFYNavigationBarTransition
Cocoapods:pod 'CFYNavigationBarTransition'