前言
苹果自IOS7之后,navigationBar增加了barTintColor属性,使得我们更加方便的设置导航栏的背景色,但是导航栏是一个比较复杂的系统控件,朋友们经常遇到设置透明不成功的问题,由于UINavigationBar是一个复合控件,因此无法像其他控件一样设置backgroundColor和alpha属性,控制导航栏的背景色和透明度,最关键的是系统导航控制器的导航栏是多个ViewController共有的,导致不同控制器导航栏不同背景色或者不同样式不好控制,正因为如此,在开发中需要自定义导航栏。
(一)导航控制器自带导航栏
(1)所有的视图控制器共用导航栏,因此存在的问题就是在当前控制器设置的导航栏属性会影响到之后的控制器,切换过程中需要不断的设置导航栏控件的属性;
(2)push控制器,导航栏会渐变;
但是,你会发现市场上很多应用导航栏在切换的过程中并没有渐变,背景色也是各种各样,因此唯有自定义导航栏能比较方便的进行相关操作,后面我会做相应的阐述。
(二)自定义导航栏
(1)通过UIView构建类似导航栏结构的视图,包括左右按钮以及titleView子视图;
(2)隐藏系统导航控制器的navigationBar,然后在ViewController控制器中创建UINavigationBar控件,并将自定义navigationItem加入创建的navigationBar中,然后通过定制navigationItem达到自定义导航栏的目的。
显然,市场上的应用大多数偏向第二种方案,原因是UINavigationBar可以很方便的设置titleView、leftButton以及rightButton。
(三)关键的两个控制器
(1)XPQBaseViewController负责统一创建navigationBar和navigationItem,子类通过继承XPQBaseViewController进行导航栏的相关配置(比如添加返回按钮或者是titleView),设置导航栏透明度方法[self.navBar.subviews objectAtIndex:0].alpha = 1 - flAlpha;
#import <UIKit/UIKit.h>
@interface XPQBaseViewController : UIViewController
@property (strong, nonatomic, readonly) UINavigationBar *navBar;
- (void)configTitleView:(UIView *)titleView;
@end
#import "XPQBaseViewController.h"
@interface XPQBaseViewController ()
@property (strong, nonatomic) UINavigationBar *navBar;
@property (strong, nonatomic) UINavigationItem *navItem;
@end
@implementation XPQBaseViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 64.f)];
self.navItem = [[UINavigationItem alloc] init];
[_navBar pushNavigationItem:_navItem animated:NO];
[self.view addSubview:_navBar];
}
- (void)configTitleView:(UIView *)titleView {
_navItem.titleView = titleView;
}
@end
(2)XPQNavigationViewController负责隐藏系统自带导航栏,且自定义导航栏侧滑手势会失效,因此需要开启侧滑手势。
#import <UIKit/UIKit.h>
@interface XPQNavigationViewController : UINavigationController
@end
#import "XPQNavigationViewController.h"
@interface XPQNavigationViewController () <UIGestureRecognizerDelegate, UINavigationControllerDelegate>
@end
@implementation XPQNavigationViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setNavigationBarHidden:YES animated:NO];
__weak XPQNavigationViewController *weakSelf = self;
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.delegate = weakSelf;
self.delegate = weakSelf;
}
}
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
// 当push控制器时,禁止侧滑手势。
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.enabled = NO;
}
if (self.viewControllers.count > 0) {
viewController.hidesBottomBarWhenPushed = YES;
}
[super pushViewController:viewController animated:animated];
}
// 当新的控制器完全显示时,开启侧滑手势。
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.enabled = YES;
}
}
// 解决当控制器子视图为根视图时侧滑返回导致的界面卡死问题。
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (self.viewControllers.count == 1) {
return NO;
}
return YES;
}
// ViewController同时接受多个手势。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
// ViewController 中的 UIScrollView(UITableView、UIWebView等滚动视图)会跟着一起滚动,并不是原始的滑动返回效果,因此通过代码设置侧滑返回只识别UIScreenEdgePanGestureRecognizer,其他手势将会识别失败。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return [gestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]];
}
@end
总结
本文XPQBaseViewController控制器只是为了说明问题,实际应用中导航栏一般都有左右按钮以及titleView,需要提供相应的属性或者是方法以便子控制器定制导航栏,在子控制器布局界面时也要考虑子视图是否遮盖自定义的navigationBar。
来源:oschina
链接:https://my.oschina.net/u/1450995/blog/603648