iOS NavigationBar顏色、透明度、隱藏設(shè)置探究

一、在項(xiàng)目開發(fā)中NavigationBar設(shè)置遇到的坑

在平時的開發(fā)中,我們往往會遇到這樣的需求,兩個ViewController的NavigationBar顏色不同、透明度不同或者有的隱藏有的不隱藏,當(dāng)兩個ViewController進(jìn)行push或pop操作時,那么你可能會看到下面現(xiàn)象:

  • 兩個ViewController的NavigationBar顏色不同,push/pop時顏色切換不和諧。
    push/pop顏色切換不和諧
    push/pop顏色切換不和諧
  • 兩個ViewController的NavigationBar隱藏設(shè)置不一樣,push/pop時隱藏NavigationBar切換不和諧。
    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解決了。效果如下:


正確的使用方法解決bug
正確的使用方法解決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'

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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