iOS自定义ViewController转场动画
$[timeformat('2021-10-08T11:09:50+08:00')]

遵守协议 <UIViewControllerAnimatedTransitioning>的动画转场管理对象

  • API
// 自定义动画时长
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 0.4;
}
// 自定义动画过程
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
}
  • 实现
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{
    return 0.3;
}
//所有的过渡动画事务都在这个方法里面完成
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{

 //取出转场前后的视图控制器
  UIViewController * fromVC = (UIViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  UIViewController * toVC = (UIViewController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

 //取出转场前后视图控制器上的视图view
    UIView * toView = [transitionContext viewForKey:UITransitionContextToViewKey];
    UIView * fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];

 //这里有个重要的概念containerView,要做转场动画的视图就必须要加入containerView上才能进行,可以理解containerView管理着所有做转场动画的视图
    UIView *containerView = [transitionContext containerView];

  //如果加入了手势交互转场,就需要根据手势交互动作是否完成/取消来做操作,完成标记YES,取消标记NO,必须标记,否则系统认为还处于动画过程中,会出现无法交互之类的bug
   [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
     if ([transitionContext transitionWasCancelled]) { 
    //如果取消转场
          }else{
   //完成转场
     }
}

继承父类UIPercentDrivenInteractiveTransition的交互动画管理对象

  • API
//必要调用实现的系统方法
//手势过程中,通过updateInteractiveTransition设置转场过程动画进行的百分比,然后系统会根据百分比自动布局动画控件,不用我们控制了
 [self updateInteractiveTransition:percentComplete];
//完成转场操作
 [self finishInteractiveTransition];
//取消转场操作
 [self cancelInteractiveTransition];

遵守<UIViewControllerTransitioningDelegate>的视图控制器转场动画管理对象

-(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
    return self.pushAnimator;
}

-(id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
    return self.popAnimator;
}

#pragma mark ------- 手势交互添加

- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator{
    
    return nil;//返回继承父类`UIPercentDrivenInteractiveTransition`的交互动画管理对象
}

- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator{
        return nil;//返回继承父类`UIPercentDrivenInteractiveTransition`的交互动画管理对象
}

使用步骤

  • 设置代理

    • push

      self.navigationController.delegate = self.animatedTransition;

    • present

      toViewController.transitioningDelegate = self.browserAnimation;

  • 分别设置 push POP 是哪个动画对象

    -(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
        return self.pushAnimator;
    }
    -(id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{
        return self.popAnimator;
    }
    - (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator{
        
        return nil;
    }
    
    - (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator{
            return nil;
    }
     
    // ---------- push 还可以这么去分配动画对象
    -(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
    
    if (operation == UINavigationControllerOperationPush) {
        return self.pushAniamtor;
        
    }else if (operation == UINavigationControllerOperationPop){
        return self.popAnimator;
    }
    return nil;
    

} ```

  • 动画对象内 设置 动画时长 和 动画实现

    - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 0.4;
    

}

  • (void)animateTransition:(id)transitionContext{ }
    
    
    
    
    
    

坑点

  • `.modalPresentationStyle = UIModalPresentationCustom;`modalPresentationStyle这个属性会影响present出来的VC的横竖屏(横屏变竖屏)