iOS NavigationBar颜色、透明度、隐藏设置探究

一、在项目开发中NavigationBar设置遇到的坑

在平时的开发中,我们往往会遇到这样的需求,两个ViewController的NavigationBar颜色不同、透明度不同或者有的隐藏有的不隐藏,当两个ViewController进行push或pop操作时,那么你可能会看到下面现象:

  • 两个ViewController的NavigationBar颜色不同,push/pop时颜色切换不和谐。
    push/pop颜色切换不和谐
    push/pop颜色切换不和谐
  • 两个ViewController的NavigationBar隐藏设置不一样,push/pop时隐藏NavigationBar切换不和谐。
    push/pop时隐藏NavigationBar切换不和谐
    push/pop时隐藏NavigationBar切换不和谐

很丑有木有O(≧口≦)O,强迫症接受不了有木有O(≧口≦)O。
  导致出现上述问题的原因是navigationBar只有一个,改变navigationBar样式一定会影响其他ViewController的显示。

二、寻找解决方案

隐藏与显示的bug解决比较简单,因为苹果已经做好了,出现上述问题的原因是,没有使用对的方法。
  隐藏NavigationBar苹果提供了两个方法:[navigationController setNavigationBarHidden:]和[navigationController setNavigationBarHidden:animated:]。第一个方法无动画隐藏navigationBar,第二个方法可以控制是否动画隐藏navigationBar。解决上述bug只需如下代码:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:NO animated:animated];
    //不要使用下面方法,下面方法会导致隐藏和不隐藏的viewController转场时出现bug
    //    [self.navigationController setNavigationBarHidden:NO];
}

OK,隐藏与显示的bug解决了。效果如下:


正确的使用方法解决bug
正确的使用方法解决bug

下面解决颜色的问题。在很多的APP都可以看到不同颜色的navigationBar的转场,但这些APP都完美的解决了颜色问题,比如微信。所以就要看看微信是如何处理的呢,这个时候就用到了一个款神奇,Mac软件Reveal,它可以看到在手机中安装的APP页面层级,至于如何使用请移步:使用Reveal查看任意App的技巧
  通过Reveal看到了微信的页面层次,如下图

微信截图
微信截图

  观察微信的层级发现,微信的navigationBar是透明的,ViewController顶部有一个view来充当navigationBar背景色,如上图左右两边的发现ViewController和小程序ViewController的顶部都有一个view,左边是黑字的右边是白色的,这样每个viewController的navigationBar的背景色就可以单独设置。

三、有了指导方向,开始动手搬砖

解决方法好像很简单,只需要在viewController.view的顶部加上一个barBgView就可以了(内心暗喜:这种代码我两分钟就可以敲完,啊哈哈哈ψ(`∇´)ψ)。
  那么开始战斗吧,啊哈哈! 哈利路亚!德玛西亚!赐给我码神的力量吧ヽ(`Д´)ノヽ(`Д´)ノヽ(`Д´)ノ!
  战斗没开始就发现遇到了坑,难道我要每个viewController里都写一遍加入barBgView的代码?不行viewController太多写起来太累;那写一个继承自viewController的父类,然后让所有viewController继承父类,不行那样还是每个viewController都要改;有没有让新项目改动极少的代码就可以实现的方法呢?答案是有的,只需要Category和黑科技Method Swizzling即可。

首先建两个UIViewController的Category.
第一个为UIViewController+CFYNavigationBarTransition.h

// UIViewController CFYNavigationBarTransition
@interface UIViewController (CFYNavigationBarTransition)
/**
 设置导航栏是否隐藏
 
 @param hidden 隐藏
 @param animated 动画
 */
- (void)cfy_setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;

@end

第二个位UINavigationController+CFYNavigationBarTransition_Public.h

@interface UIViewController (CFYNavigationBarTransition_Public)

/**
 设置导航栏背景色
 
 @param color 背景色
 */
- (void)cfy_setNavigationBarBackgroundColor:(UIColor *)color;

/**
 设置背景图片

 @param image 背景图
 */
- (void)cfy_setNavigationBarBackgroundImage:(UIImage *)image;

/**
 设置导航栏透明度
 
 @param alpha 透明度
 */
- (void)cfy_setNavigationBarAlpha:(CGFloat)alpha;

/**
 bar背景色
 */
@property (readonly) UIColor *cfy_navigationBarBackgroundColor;

/**
 bar透明度
 */
@property (readonly) CGFloat cfy_navigationBarAlpha;

@end

两个都是UIViewController的Category,以public结尾的文件中是对外提供公开的方法和属性,也就是用户可以使用的方法和属性,另个则是放私有方法和属性。
  两个category中方法和属性的实现都在UIViewController+CFYNavigationBarTransition.m中实现,实现逻辑加在了注释中

@interface UIViewController ()

/**
 cfy_navBarBgView,这个view就是核心,改变navigationBar颜色其实是改变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进行处理,使cfy_navBarBgView能在不同环境正确显示
 */
- (void)cfy_viewWillLayoutSubviews {
    [self cfy_viewWillLayoutSubviews];
    // 当前viewController没navigationController,直接退出
    if (!self.navigationController) {
        return;
    }
    /**
     self.navigationController.navigationBar隐藏了,做一些处理。
     如果在navigationBar隐藏时,旋转屏幕,这时如果不处理后并return,而是走下面的代码,那么并不能正确的获取到cfy_navBarBgView的frame。
     所以在这里直接将cfy_navBarBgView的宽度设置成屏幕看度,其他不变保持cfy_navBarBgView在隐藏前的状态,这样在从竖屏切换到横屏显示时不会出现一些视觉上的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];
    
    // 出现rect.origin.x < 0,情况只有在页面刚push出来并且navigationBar隐藏的时候。
    // 这个时候讲rect.origin.y上移rect.size.height,使cfy_navBarBgView也隐藏
    // 目的是防止在navigationBar.hidden=NO时出现动画显示错误
    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);
    
    // 设置当前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 - 公开方法 -
/**
 设置导航栏背景色
 
 @param color 背景色
 */
- (void)cfy_setNavigationBarBackgroundColor:(UIColor *)color {
    self.cfy_navigationBarBackgroundColor = color;
    if (self.navigationController) {
        self.cfy_navBarBgView.backgroundColor = color;
    }
}

/**
 设置背景图片
 
 @param image 背景图
 */
- (void)cfy_setNavigationBarBackgroundImage:(UIImage *)image {
    // 后续版本加入
}

/**
 设置导航栏透明度
 
 @param alpha 透明度
 */
- (void)cfy_setNavigationBarAlpha:(CGFloat)alpha {
    self.cfy_navigationBarAlpha = alpha;
    if (self.navigationController) {
        self.cfy_navBarBgView.alpha = alpha;
    }
}

#pragma mark - 私有方法 -
/**
 设置导航栏是否隐藏
 
 @param hidden 隐藏
 @param animated 动画
 */
- (void)cfy_setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {
    if (self.navigationController) {
        // 这里只在cfy_navBarBgView隐藏时使用了动画,原因是cfy_navBarBgView显示时系统自动给加上了动画(这很神奇)
        if (hidden && self.cfy_viewAppeared && animated && !self.navigationController.navigationBar.hidden) {
            // 在cfy_navBarBgView隐藏,并且view已经Appeared,并且有动画,并且navigationBar不是已经隐藏了时就进行动画
            CGRect rect = self.cfy_navBarBgView.frame;
            [UIView animateWithDuration:0.2 animations:^{
                // 动画时向上运动
                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在当前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];
    
    // 判断有没有设置颜色
    if (self.cfy_navigationBarBackgroundColor) {
        navBarBgView.backgroundColor = self.cfy_navigationBarBackgroundColor;
    } else {
        // 默认是白色
        navBarBgView.backgroundColor = [UIColor whiteColor];
        self.cfy_navigationBarBackgroundColor = [UIColor whiteColor];
    }
    // 设置透明度,默认为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:在设置[navigationController setNavigationBarHidden:animated:]和[navigationController setNavigationBarHidden:]方法是应该对cfy_navBarBgView进行操作;
  • 问题2:没有设置NavigationBar为透明,不设置成透明,前面的工作都白做了。

那么对navigationController也建一个Category,并swizzle需要的方法。代码如下:
UIViewController+CFYNavigationBarTransition.m

@interface UIViewController ()

/**
 cfy_navBarBgView,这个view就是核心,改变navigationBar颜色其实是改变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进行处理,使cfy_navBarBgView能在不同环境正确显示
 */
- (void)cfy_viewWillLayoutSubviews {
    [self cfy_viewWillLayoutSubviews];
    // 当前viewController没navigationController,直接退出
    if (!self.navigationController) {
        return;
    }
    /**
     self.navigationController.navigationBar隐藏了,做一些处理。
     如果在navigationBar隐藏时,旋转屏幕,这时如果不处理后并return,而是走下面的代码,那么并不能正确的获取到cfy_navBarBgView的frame。
     所以在这里直接将cfy_navBarBgView的宽度设置成屏幕看度,其他不变保持cfy_navBarBgView在隐藏前的状态,这样在从竖屏切换到横屏显示时不会出现一些视觉上的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];
    
    // 出现rect.origin.x < 0,情况只有在页面刚push出来并且navigationBar隐藏的时候。
    // 这个时候讲rect.origin.y上移rect.size.height,使cfy_navBarBgView也隐藏
    // 目的是防止在navigationBar.hidden=NO时出现动画显示错误
    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);
    
    // 设置当前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 - 公开方法 -
/**
 设置导航栏背景色
 
 @param color 背景色
 */
- (void)cfy_setNavigationBarBackgroundColor:(UIColor *)color {
    self.cfy_navigationBarBackgroundColor = color;
    if (self.navigationController) {
        self.cfy_navBarBgView.backgroundColor = color;
    }
}

/**
 设置背景图片
 
 @param image 背景图
 */
- (void)cfy_setNavigationBarBackgroundImage:(UIImage *)image {
    // 后续版本加入
}

/**
 设置导航栏透明度
 
 @param alpha 透明度
 */
- (void)cfy_setNavigationBarAlpha:(CGFloat)alpha {
    self.cfy_navigationBarAlpha = alpha;
    if (self.navigationController) {
        self.cfy_navBarBgView.alpha = alpha;
    }
}

#pragma mark - 私有方法 -
/**
 设置导航栏是否隐藏
 
 @param hidden 隐藏
 @param animated 动画
 */
- (void)cfy_setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {
    if (self.navigationController) {
        // 这里只在cfy_navBarBgView隐藏时使用了动画,原因是cfy_navBarBgView显示时系统自动给加上了动画(这很神奇)
        if (hidden && self.cfy_viewAppeared && animated && !self.navigationController.navigationBar.hidden) {
            // 在cfy_navBarBgView隐藏,并且view已经Appeared,并且有动画,并且navigationBar不是已经隐藏了时就进行动画
            CGRect rect = self.cfy_navBarBgView.frame;
            [UIView animateWithDuration:0.2 animations:^{
                // 动画时向上运动
                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在当前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];
    
    // 判断有没有设置颜色
    if (self.cfy_navigationBarBackgroundColor) {
        navBarBgView.backgroundColor = self.cfy_navigationBarBackgroundColor;
    } else {
        // 默认是白色
        navBarBgView.backgroundColor = [UIColor whiteColor];
        self.cfy_navigationBarBackgroundColor = [UIColor whiteColor];
    }
    // 设置透明度,默认为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的颜色,调用[viewController cfy_setNavigationBarBackgroundColor:bgColor]方法。
  • 改变navigationBar的透明度,调用[viewController cfy_setNavigationBarAlpha:alpha]方法.
  • 隐藏则直接调用UINavigationController中设置NavigationBar隐藏的方法
    注意事项:不要设置NavigationBar的translucent为NO,原因是设置了translucent=NO,NavigationBar就不能透明了。

四、成果展示

竖屏效果
竖屏效果

横屏效果
横屏效果

五、代码地址

GitHub: CFYNavigationBarTransition
Cocoapods:pod 'CFYNavigationBarTransition'

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容