博客> 自定义NavigationController用法
自定义NavigationController用法
2017-12-12 12:52 评论:0 阅读:97 进击的可乐SAMA

1.自定义navigationbar完成各种要求(自定义一个viewController的类,让其他页面继承这个类,并让系统的navigationbar隐藏起来)


#import "BaseViewController.h"

@interface BaseViewController ()
//自定义imageView用来承载背景图片 默认隐藏
@property (nonatomic, strong)UIImageView * navBackgroundImageView;
//自定义statusBar
@property (nonatomic, strong)UIView * navStatusView;
//对外 根据type来判断需要用哪种navigationbar
@property (nonatomic, assign)NSInteger navType;
//自定义navigationbar
@property (nonatomic, strong)UINavigationBar * navigationBar;
//自定义navigationItem 用来承载左右侧按钮和标题视图
@property (nonatomic, strong)UINavigationItem * navigationItem;
//标题视图
@property (nonatomic, strong)UIView * navTitleView;
//左侧视图
@property (nonatomic, strong)UIView * leftView;
//右侧视图
@property (nonatomic, strong)UIView * rightView;

@end

@implementation BaseViewController
//将初始化写在viewWillAppear中 使初始化在viewDidLoad方法之后执行
- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    if (self.navigationBar == nil) {
        self.navStatusView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 375, 20)];
        self.navStatusView.backgroundColor = [UIColor whiteColor];
        [self.view addSubview:self.navStatusView];

        self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 20, 375, 44)];
        [self.view addSubview:self.navigationBar];

        self.navigationItem = [[UINavigationItem alloc] init];
        if (self.navTitleView) {
            self.navigationItem.titleView = self.navTitleView;
        }

        self.navBackgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, -20, 375, 64)];
        [self.navigationBar insertSubview:self.navBackgroundImageView atIndex:0];
        self.navBackgroundImageView.hidden = YES;
        [self.navigationBar pushNavigationItem:self.navigationItem animated:YES];

        //给navigationbar随意设置图片
        if (self.navType == 1) {
            self.navStatusView.hidden = YES;
            [self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
            [self.navigationBar setShadowImage:[UIImage new]];
            self.navBackgroundImageView.hidden = NO;
            self.navBackgroundImageView.image = [UIImage imageNamed:@"bg_title_all"];

        //使navigationbar隐藏起来
        }else if (self.navType == 2){
            self.navStatusView.hidden = YES;
            [self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
            [self.navigationBar setShadowImage:[UIImage new]];

        //普通的白色navigationbar
        }else if (self.navType == 0){
            self.navigationBar.translucent = NO;
        }

        if (self.leftView) {
            self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.leftView];
        }

        if (self.rightView) {
            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.rightView];
        }
    }

}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

2.自定义NavigationController,给NavigationController添加滑动手势,使视图可以滑动翻页


//.h
#import {UIKit/UIKit.h}

@interface LYNavigationController : UINavigationController

@end
//.m
#import "LYNavigationController.h"
#import "NavigationInteractiveTransition.h"
#import "PopAnimation.h"

@interface LYNavigationController (){UIGestureRecognizerDelegate,UINavigationControllerDelegate}
//监控动画的类,用来监控视图中的滑动动画
@property (nonatomic, strong)UIPercentDrivenInteractiveTransition * interativePopTransition;
//是否禁止滑动,一般对外使用
@property (nonatomic, assign)BOOL stopSlip;

@end

@implementation LYNavigationController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.delegate = self;
    //隐藏navigationbar,使用自定义navigationbar
    self.navigationBar.hidden = YES;
    //禁止使用系统自带的滑动手势
    self.interactivePopGestureRecognizer.enabled = NO;
    //创建全屏滑动手势
    UIPanGestureRecognizer * gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleControllerPop:)];
    //设置手势代理,拦截手势触发
    gesture.delegate = self;
    //给导航控制器的view添加全屏滑动手势
    [self.view addGestureRecognizer:gesture];
}

//把用户的每次滑动手势操作作为一次pop动画的执行
- (void)handleControllerPop:(UIPanGestureRecognizer *)gesture{
    //计算出进度
    CGFloat progress = [gesture translationInView:gesture.view].x / gesture.view.bounds.size.width;
    //[gesture translationInView:gesture.view].x 计算出横向滑动了多少像素

    //此时说一下手势的各个状态 即手势的state:gesture.state
    /*
     UIGestureRecognizerStatePossible:起初的默认状态,表示将会滑动
     UIGestureRecognizerStateBegan:手势开始滑动的状态
     UIGestureRecognizerStateChanged:滑动手势坐标改变时候的状态
     UIGestureRecognizerStateEnded:滑动手势停止时的状态
     UIGestureRecognizerStateCancelled:取消滑动手势时的状态
     UIGestureRecognizerStateFailed:手势失败的状态
     UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
     */

    //手势一旦开始,给动画加上监控 并让navigationcontroller执行pop动画
    if (gesture.state == UIGestureRecognizerStateBegan) {
        self.interativePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init];
        self.interativePopTransition.completionCurve = UIViewAnimationCurveEaseOut;
        [self popViewControllerAnimated:YES];

        //如果手势处于改变的状态 则更新动画的进度
    }else if (gesture.state == UIGestureRecognizerStateChanged){
        [self.interativePopTransition updateInteractiveTransition:progress];

        //如果手势停止或者取消了
    }else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled){
        //如果动画进度大于0.2,那么使动画做完
        if (progress > 0.2) {
            [self.interativePopTransition finishInteractiveTransition];

            //不然的话使动画取消
        }else{
            [self.interativePopTransition cancelInteractiveTransition];
        }
        self.interativePopTransition = nil;
    }
}

//方法1
- (id{UIViewControllerAnimatedTransitioning})navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
    //如果当前执行的是pop操作,就返回我们自定义的pop动画对象。
    if (operation == UINavigationControllerOperationPop){
            __weak typeof(self)weakSelf = self;
            [UIView animateWithDuration:0.25 animations:^{
                [weakSelf.navigationBar endEditing:YES];
                [fromVC.view endEditing:YES];
            }];
        return [[PopAnimation alloc] init];
    }
    //如果是push操作,则返回空
    if (operation == UINavigationControllerOperationPush) {
        return nil;
    }
    return nil;
}

//方法2,提供交互式动画:
- (id{UIViewControllerInteractiveTransitioning})navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id{UIViewControllerAnimatedTransitioning})animationController {
    /**
     *  方法2会传给你当前的动画对象animationController,判断如果是我们自定义的Pop动画对象,那么就返回interactivePopTransition来监控动画完成度。
     */
    if ([animationController isKindOfClass:[PopAnimation class]]){
        return self.interativePopTransition;
    }
    return nil;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    // 注意:只有非根控制器才有滑动返回功能,根控制器没有。
    // 判断导航控制器是否只有一个子控制器,如果只有一个子控制器,肯定是根控制器
    if (self.childViewControllers.count == 1) {
        // 表示用户在根控制器界面,就不需要触发滑动手势,
        return NO;
    }
    //yes为停止滑动
    if (_stopSlip == YES){
        return NO;
    }

    return YES;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

3.自定义pop动画


//.h
#import {Foundation/Foundation.h}
#import {UIKit/UIKit.h}

@interface PopAnimation : NSObject {UIViewControllerAnimatedTransitioning}

@end

//.m
#import "PopAnimation.h"
#import "HAJTabBarViewController.h"
#import "HAJNavigationController.h"
#import "HAJFirstViewController.h"
#import "HAJTabBar.h"
@interface PopAnimation ()
@property (nonatomic, strong) id {UIViewControllerContextTransitioning} transitionContext;
@end

@implementation PopAnimation

- (NSTimeInterval)transitionDuration:(id {UIViewControllerContextTransitioning})transitionContext {
    //这个方法返回动画执行的时间
    return 0.35;
}

/**
 *  transitionContext你可以看作是一个工具,用来获取一系列动画执行相关的对象,并且通知系统动画是否完成等功能。
 */

- (void)animateTransition:(id {UIViewControllerContextTransitioning})transitionContext {

    /**
     *  获取动画来自的那个控制器
     */
    __block UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    /**
     *  获取转场到的那个控制器
     */
    __block UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    __block UIView *maskView = [UIView new];
    maskView.frame = [UIScreen mainScreen].bounds;
    maskView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.2];
    __block UIView *shadowView = [[UIView alloc]init];
    shadowView.frame = CGRectMake(fromViewController.view.x, 0, 3, ScreenHeight);
    shadowView.backgroundColor = [UIColor lightGrayColor];
    shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
    shadowView.layer.shadowRadius = 2;
    shadowView.layer.shadowOpacity = 0.3;
    shadowView.layer.shadowOffset = CGSizeMake(-2,0);
    /**
     *  转场动画是两个控制器视图时间的动画,需要一个containerView来作为一个“舞台”,让动画执行。
     */
    UIView *containerView = [transitionContext containerView];

    [containerView insertSubview:toViewController.view belowSubview:fromViewController.view];
    //底部tabBar copy及snapshot 置于fromVC的底下
    __block HAJTabBar *tabBarCopy;
    __block UIView *snapshotTabBar;
    if (toViewController.navigationController.childViewControllers.count == 1) {

        tabBarCopy = [toViewController.tabBarController.tabBar copy];
        snapshotTabBar = [toViewController.tabBarController.tabBar snapshotViewAfterScreenUpdates:YES];
        [tabBarCopy addSubview:snapshotTabBar];
        [toViewController.view addSubview:tabBarCopy];
        [containerView insertSubview:tabBarCopy belowSubview:fromViewController.view];
        if (toViewController.tabBarController.tabBar.hidden == YES) {
            tabBarCopy.hidden = YES;
        }
    }
    [containerView insertSubview:maskView belowSubview:fromViewController.view];
    [containerView insertSubview:shadowView belowSubview:fromViewController.view];

    NSTimeInterval duration = [self transitionDuration:transitionContext];
    toViewController.tabBarController.tabBar.x = [UIScreen mainScreen].bounds.origin.x;
    toViewController.tabBarController.tabBar.y = [UIScreen mainScreen].bounds.size.height;
    toViewController.view.x = fromViewController.view.x - toViewController.view.width + toViewController.view.width / 2;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        toViewController.tabBarController.tabBar.alpha = 0;
    });

    tabBarCopy.frame = CGRectMake(toViewController.view.x, [UIScreen mainScreen].bounds.size.height - 49, [UIScreen mainScreen].bounds.size.width, 49);
    snapshotTabBar.frame = CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.width, 49);

    /**
     *  执行动画,我们让fromVC的视图移动到屏幕最右侧
     */
    [UIView animateWithDuration:duration animations:^{
        fromViewController.view.transform = CGAffineTransformMakeTranslation([UIScreen mainScreen].bounds.size.width, 0);
        toViewController.view.x = fromViewController.view.x - toViewController.view.width;
        tabBarCopy.x = toViewController.view.x;
        maskView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
        shadowView.frame = CGRectMake(fromViewController.view.x, 0, 3, ScreenHeight);
    }completion:^(BOOL finished) {
        if (tabBarCopy) {
            [tabBarCopy removeFromSuperview];
            tabBarCopy = nil;
        }
        [maskView removeFromSuperview];
        maskView = nil;
        [shadowView removeFromSuperview];
        shadowView = nil;
        toViewController.tabBarController.tabBar.alpha = 1;
        toViewController.tabBarController.tabBar.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 49, [UIScreen mainScreen].bounds.size.width, 49);
        /**
         *  当你的动画执行完成,这个方法必须要调用,否则系统会认为你的其余任何操作都在动画执行过程中。
         */

        [transitionContext completeTransition:!transitionContext.transitionWasCancelled];

    }];

    _transitionContext = transitionContext;
    //----------------pop动画一-------------------------//
    /*
    [UIView beginAnimations:@"View Flip" context:nil];
    [UIView setAnimationDuration:duration];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:containerView cache:YES];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:)];
    [UIView commitAnimations];提交UIView动画
    [containerView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
    */
    //----------------pop动画二-------------------------//
    /*
    CATransition *tr = [CATransition animation];
    tr.type = @"cube";
    tr.subtype = @"fromLeft";
    tr.duration = duration;
    tr.removedOnCompletion = NO;
    tr.fillMode = kCAFillModeForwards;
    tr.delegate = self;
    [containerView.layer addAnimation:tr forKey:nil];
    [containerView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
     */
}

- (void)animationDidStop:(CATransition *)anim finished:(BOOL)flag {
    [_transitionContext completeTransition:!_transitionContext.transitionWasCancelled];
}

@end
收藏
0
sina weixin mail 回到顶部