ios中导航栏是一个很头疼的东西,由于navigationbar是统一设置,没法实现每一个页面有本身的导航栏样式。解决的办法有两个,ios
一、隐藏系统自带的self.navigationViewController.navigationBar,在baseViewController中本身添加一个navigationBar,这样就能够在每一个vc中设置本身的样式了git
优势:各管各的,不会相互影响,使用方便github
缺点:不会有过分渐变效果,每一个页面都建立navigationBar,消耗稍微大点app
二、在vc出现的时候时(viewWillAppear)从新设置导航栏样式ide
优势:系统原生,效率高,可自定义导航栏过渡动画效果函数
缺点:容易出坑动画
-----------------------------凌乱分割线-----------------------------spa
接下来以第二种方法为例,看看怎么设置导航栏样式:code
默认导航栏只有两个样式:黑色毛玻璃和白色毛玻璃orm
[self.navigationController.navigationBar setBarStyle:UIBarStyleBlack];
设置导航栏的颜色:
[self.navigationController.navigationBar setBarTintColor:[UIColor blueColor]];
因为模式缘由,会混上白色或者黑色蒙蔽+背景高斯模糊效果,因此设置的意思未必是你想要的真正颜色,网上有些颜色转换的方法,可是我试了都不是特别准,写一个相对好点的
- (UIColor *)barColorTransitionWithColor:(UIColor *)color { CGFloat red, green, blue, alpha; [color getRed:&red green:&green blue:&blue alpha:&alpha]; CGFloat opacity = 0.4; CGFloat minVal = MIN(MIN(red, green), blue); if ([self convertValue:minVal withOpacity:opacity] < 0) { opacity = [self minOpacityForValue:minVal]; } red = [self convertValue:red withOpacity:opacity]; green = [self convertValue:green withOpacity:opacity]; blue = [self convertValue:blue withOpacity:opacity]; red = MAX(MIN(1.0, red), 0); green = MAX(MIN(1.0, green), 0); blue = MAX(MIN(1.0, blue), 0); return [UIColor colorWithRed:red green:green blue:blue alpha:1.]; } - (CGFloat)minOpacityForValue:(CGFloat)value { return (0.4 - 0.4 * value) / (0.6 * value + 0.4); } - (CGFloat)convertValue:(CGFloat)value withOpacity:(CGFloat)opacity { return 0.4 * value / opacity + 0.6 * value - 0.4 / opacity + 0.4; }
直接设置navigationBar的alpha是什么效果的,须要获取到navigation的subview,这里ios10的subview类名有所改变,因此要特殊处理
NSString *backgroundViewClass = @"_UINavigationBarBackground"; if (IOS10) { backgroundViewClass = @"_UIBarBackground"; } for (UIView * subView in self.subviews) { if ([subView isKindOfClass:NSClassFromString(backgroundViewClass)]) { [self setOverlay:subView]; return subView; } }
设置这个subview的alpha就能达到导航栏的透明度,而不影响导航栏上面item
一样能够遍历navbar的subview获取到分割线的view进行控制
- (UIImageView *)yxBottomLine:(UIView *)view { if ([view isKindOfClass:[UIImageView class]] && view.bounds.size.height <= 1.0) { return (UIImageView *)view; } for (UIView *subView in view.subviews) { UIImageView *imageView = [self yxBottomLine:subView]; if (imageView) { return imageView; } } return nil; }
[self.navigationController.navigationBar setTintColor:color];
NSDictionary *attributes=[NSDictionary dictionaryWithObjectsAndKeys:titleColor, NSForegroundColorAttributeName, [UIFont boldSystemFontOfSize:17], NSFontAttributeName, nil]; [self.navigationController.navgationBar setTitleTextAttributes:attributes];
[[self transitionCoordinator] animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { [self updateNavigationBarType:type]; } completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) { if (![context isCancelled]) { [self updateNavigationBarType:type]; } }];
在导航栏样式发送变化的时候放到这个函数里来,ps:ios10过分动画不理想,能够ios10参考第一中方法实现
- (void)updateNavBackItemIcon { [self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"icon_navigation_back"]]; [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"icon_navigation_back"]]; [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes: @{NSFontAttributeName:[UIFont systemFontOfSize:15.0]} forState:UIControlStateNormal]; }
我已经写好的导航栏样式库:https://github.com/Jonear/JNNavigation (欢迎你们使用)