导航控制器的过场动画

导航控制器过场动画的实现过程:

  • 自定义导航控制器,并设置代理为设置self,实现navigationController: animationControllerForOperation: fromViewController: toViewController:
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.delegate = self;
}

- (id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
    AnimatedTransition1 *t1 = [[AnimatedTransition1 alloc] init];
    t1.operation = operation;
    return t1;
}
  • 自定义AnimatedTransition1 : NSObject。在navigationController: animationControllerForOperation: fromViewController: toViewController:返回该类的对象。
// 指定动画时间
- (NSTimeInterval)transitionDuration:(id)transitionContext {
    return 1;
}

// 动画怎么执行
- (void)animateTransition:(id)transitionContext {
    // 执行动画所需的代码
}

过场动画上下文

UIViewControllerAnimatedTransitioning协议中的代理方法- (void)animateTransition:中有一个UIViewControllerContextTransitioning类型的参数:transitionContext-过场动画上下文。

  • 可获取控制器:fromVC、toVC
  • 可获取视图:fromView、toView
  • 可获取视图的初始化frame与最终frame:fromViewInitFrame、toViewInitFrame、fromViewFinalFrame、toViewFinalFrame
  • containerView,并且containerView已经拥有fromView。toVC则需要手动添加。
导航控制器的过场动画_第1张图片
frame-push.png

导航控制器的过场动画_第2张图片
frame-pop.png

下面提供一个实现动画的demo:

- (void)animateTransition:(id)transitionContext {
    UIView *containerView = transitionContext.containerView;
    
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
    UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
    
    CGRect fromViewInitFrame = [transitionContext initialFrameForViewController:fromVC];
    CGRect toViewInitFrame = [transitionContext initialFrameForViewController:fromVC];
    
    CGRect fromViewFinalFrame = [transitionContext finalFrameForViewController:fromVC];
    CGRect toViewFinalFrame = [transitionContext finalFrameForViewController:toVC];
    
    [containerView addSubview:toView];
    
    if (self.operation == UINavigationControllerOperationPush) {
        fromViewInitFrame.origin.y = 0;
        toViewInitFrame.origin.y = -fromViewInitFrame.size.height;
        fromViewFinalFrame = fromViewInitFrame;
    } else if (self.operation ==  UINavigationControllerOperationPop) {
        fromViewInitFrame.origin.y = 0;
        toViewInitFrame.origin.y = 0;
        fromViewFinalFrame = fromViewInitFrame;
        fromViewFinalFrame.origin.y = -fromViewInitFrame.size.height;
        [containerView sendSubviewToBack:toView];
    }
    
    fromView.frame = fromViewInitFrame;
    toView.frame = toViewInitFrame;
    
    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
        fromView.frame = fromViewFinalFrame;
        toView.frame = toViewFinalFrame;
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:YES];
    }];
}

demo代码地址

你可能感兴趣的:(导航控制器的过场动画)