iOS如何自定义控制器转场动画push详解

2020-01-21 03:33:14王冬梅

在控制器里面用来自定义转场动画的方法里返回刚才自定义的动画类


- (id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{  
 if (operation == UINavigationControllerOperationPush) {
  return [LRTranstionAnimationPush new];
 }else{
  return nil;
 }
}

到此为止自定义转场动画就完成了

pop的动画只是把push动画反过来做一遍这里就不细讲了,有疑问的可以去看代码

添加滑动返回手势

上面说到这个方法是为这个动画添加用户交互的所以我们要在pop时实现滑动返回

最简单的方式应该就是利用UIKit提供的UIPercentDrivenInteractiveTransition类了,这个类已经实现了UIViewControllerInteractiveTransitioning协议,同学men可以通过这个类的对象指定转场动画的完成百分比。


//为这个动画添加用户交互
- (nullable id)navigationController:(UINavigationController *)navigationController       interactionControllerForAnimationController:(id) animationController NS_AVAILABLE_IOS(7_0);

第一步 添加手势


 UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
 [self.view addGestureRecognizer:gestureRecognizer];

第二步 通过用户滑动的变化确定动画执行的比例


- (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer {  
 /*调用UIPercentDrivenInteractiveTransition的updateInteractiveTransition:方法可以控制转场动画进行到哪了,
  当用户的下拉手势完成时,调用finishInteractiveTransition或者cancelInteractiveTransition,UIKit会自动执行剩下的一半动画,
  或者让动画回到最开始的状态。*/   
 if ([gestureRecognizer translationInView:self.view].x>=0) {
  //手势滑动的比例
  CGFloat per = [gestureRecognizer translationInView:self.view].x / (self.view.bounds.size.width);
  per = MIN(1.0,(MAX(0.0, per)));   
  if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {    
   self.interactiveTransition = [UIPercentDrivenInteractiveTransition new];
   [self.navigationController popViewControllerAnimated:YES];    
  } else if (gestureRecognizer.state == UIGestureRecognizerStateChanged){    
   if([gestureRecognizer translationInView:self.view].x ==0){     
    [self.interactiveTransition updateInteractiveTransition:0.01];     
   }else{     
    [self.interactiveTransition updateInteractiveTransition:per];
   }    
  } else if (gestureRecognizer.state == UIGestureRecognizerStateEnded || gestureRecognizer.state == UIGestureRecognizerStateCancelled){    
   if([gestureRecognizer translationInView:self.view].x == 0){     
    [self.interactiveTransition cancelInteractiveTransition];
    self.interactiveTransition = nil;     
   }else if (per > 0.5) {     
    [ self.interactiveTransition finishInteractiveTransition];
   }else{
     
    [ self.interactiveTransition cancelInteractiveTransition];
   }
   self.interactiveTransition = nil;
  }     
 } else if (gestureRecognizer.state == UIGestureRecognizerStateChanged){
  [self.interactiveTransition updateInteractiveTransition:0.01];
  [self.interactiveTransition cancelInteractiveTransition]; 
 } else if ((gestureRecognizer.state == UIGestureRecognizerStateEnded || gestureRecognizer.state == UIGestureRecognizerStateCancelled)){   
  self.interactiveTransition = nil;
 }  
}