iOS-自定义导航栏

前言ide

苹果自IOS7以后,navigationBar增长了barTintColor属性,使得咱们更加方便的设置导航栏的背景色,可是导航栏是一个比较复杂的系统控件,朋友们常常遇到设置透明不成功的问题,因为UINavigationBar是一个复合控件,所以没法像其余控件同样设置backgroundColor和alpha属性,控制导航栏的背景色和透明度,最关键的是系统导航控制器的导航栏是多个ViewController共有的,致使不一样控制器导航栏不一样背景色或者不一样样式很差控制,正由于如此,在开发中须要自定义导航栏。布局

 

(一)导航控制器自带导航栏ui

(1)全部的视图控制器共用导航栏,所以存在的问题就是在当前控制器设置的导航栏属性会影响到以后的控制器,切换过程当中须要不断的设置导航栏控件的属性;atom

(2)push控制器,导航栏会渐变;code

可是,你会发现市场上不少应用导航栏在切换的过程当中并无渐变,背景色也是各类各样,所以惟有自定义导航栏能比较方便的进行相关操做,后面我会作相应的阐述。继承

 

(二)自定义导航栏开发

(1)经过UIView构建相似导航栏结构的视图,包括左右按钮以及titleView子视图;it

(2)隐藏系统导航控制器的navigationBar,而后在ViewController控制器中建立UINavigationBar控件,并将自定义navigationItem加入建立的navigationBar中,而后经过定制navigationItem达到自定义导航栏的目的。io

显然,市场上的应用大多数偏向第二种方案,缘由是UINavigationBar能够很方便的设置titleView、leftButton以及rightButton。class

 

(三)关键的两个控制器

(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。

相关文章
相关标签/搜索