美文网首页
ios 转场动画的制作

ios 转场动画的制作

作者: 10m每秒滑行 | 来源:发表于2017-02-21 16:23 被阅读0次

    直接看转场动画的协议时有点迷糊,做了一个简单的demo记录下理解过程

    一、如何更改动画方式

    站在自己的角度,最简单的理解是,要想制作一个自定义的转场动画,来避开原生的push和present的效果,则要更改系统默认动画的代理。

    1.如果你使用的是navigationController的pushViewController方法,则要更改navigationController的delegate,并在delegate方法:

    - (nullableid)navigationController:(UINavigationController*)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation

    fromViewController:(UIViewController*)fromVC

    toViewController:(UIViewController*)toVC;

    {

    return[customerAnimator new];//返回一个自定义的动画执行者

    }

    2.如果你使用的是[currentVCpresentViewController:newVCanimated:YEScompletion:nil];来present新页面的话,则需要重新设置newVC的transitioningDelegate这个代理是实现了UIViewControllerTransitioningDelegate协议的对象并在delegate中实现协议的以下两个方法

    - (nullableid)animationControllerForDismissedController:(UIViewController*)dismissed;

    {

    return[customerAnimator new];//返回一个自定义的动画执行者,在customerAnimator才实现真正的动画效果,此方法是这个页面dismiss的之后询问的代理方法,问动画由设来执行。

    }

    - (nullableid)animationControllerForPresentedController:(UIViewController*)presented presentingController:(UIViewController*)presenting sourceController:(UIViewController*)source;

    {

    return[customerAnimator new];//返回一个自定义的动画执行者,此方法在页面出现时询问,问出现的动画由谁来执行。

    }


    二、动画的实际效果怎么实现

    从上面的协议方法中可以看出,协议最终都要求返回一个遵循UIViewControllerAnimatedTransitioning协议的对象,即customerAnimator,这个对象充当动画的执行者角色。

    也就是说,这个执行者必须按照协议规定的样子去执行转场,这个animator必须实现的两个协议方法是:

    //1.执行动画所需要的时间

    - (NSTimeInterval)transitionDuration:(nullableid)transitionContext;

    //2.转场动画效果具体实现在这个方法中去实现

    - (void)animateTransition:(id)transitionContext;

    所以可以看出,整个过程中核心是animator(动画的执行者)在起作用,核心方法是- (void)animateTransition:(id)transitionContext ,负责实现实际的效果实现

    //简单的示例

    - (void)animateTransition:(id)transitionContext {

    //如何切换两个View,设置和动画写在此处

    //toVC

    UIViewController*toVC = [transitionContextviewControllerForKey:UITransitionContextToViewControllerKey];

    //finally rect

    CGRectfinallyRect = [transitionContextfinalFrameForViewController:toVC];

    toVC.view.frame=CGRectOffset(finallyRect,0, [UIScreenmainScreen].bounds.size.height);

    //3

    [[transitionContextcontainerView]addSubview:toVC.view];

    //4

    [UIViewanimateWithDuration:[selftransitionDuration:transitionContext]delay:0.0options:UIViewAnimationOptionCurveLinearanimations:^{

    toVC.view.frame= finallyRect;

    }completion:^(BOOLfinished) {

    [transitionContextcompleteTransition:YES];

    }];

    }



    三、基于手势的转场动画

    当在animator中实现了动画效果后,要想在手指向右滑动的过程中,动画也跟着手指的滑动程度去更新动画的执行程度,则需要实现一个代理方法,用于返回标志动画执行的百分比的实例。

    同样,如果是使用UIviewController presentViewController 的方式 则是实现UIViewControllerTransitioningDelegate协议的方法

    - (nullableid)interactionControllerForDismissal:(id)animator{

    _persentDriver =[UIPercentDrivenInteractiveTransition new];

    return_persentDriver;//此实例中纪录了动画执行的persent

    }

    //用于提供消失的时候的手势百分比

    如果是使用navigationController的push方法将viewController推出的,则需要实现naviagtionControllerDelegate协议的

    - (nullableid)navigationController:(UINavigationController*)navigationController interactionControllerForAnimationController:(id) animationController {

    _persentDriver =[UIPercentDrivenInteractiveTransition new];

    return_persentDriver;

    }

    代理方法

    为了达到手在滑动的过程中动画跟着手指执行,需要在给viewontroller的view加一个滑动手势

    UIPanGestureRecognizer*panGesture = [[UIPanGestureRecognizeralloc]initWithTarget:selfaction:@selector(handPanGesture:)];

    [self.viewaddGestureRecognizer:panGesture];

    - (void)hanPanGesture:(UIPanGestureRecognizer*)gesture {

         CGPointpoint = [gesturetranslationInView:_viewController.view];

         switch(gesture.state) {

               caseUIGestureRecognizerStateBegan:

               {

                    if(point.y>0) {

                           if(![self isBePresent])

                                    //push进来的

                                   [self.navigationControllerpopViewControllerAnimated:YES];

                            }else{

                                     //present进来的

                                      [selfdismissViewControllerAnimated:YEScompletion:^{

                                        }];

                           }

                    }

    }                                                                                                                                            break;                                                                                                                                  case  UIGestureRecognizerStateChanged:                                                                        {                                                                                                                                                    CGFloatpersent = point.y/200.0;                                                                                          [_persentDriverupdateInteractiveTransition:persent];//更新动画的百分比                   }                                                                                                                                          break;                                                                                                                                  case  UIGestureRecognizerStateCancelled:                                                                      case  UIGestureRecognizerStateEnded:                                                                             {                                                                                                                                               [_persentDriverfinishInteractiveTransition];                                                                     }                                                                                                                                    break;                                                                                        

     default:

     break;                                                                                                                                   } }

    - (BOOL)isBePresented {

            if(self.navigationController) {

                   NSArray*viewcontrollers=self.navigationController.viewControllers;

                  if(viewcontrollers.count>1) {

                           if([viewcontrollersobjectAtIndex:viewcontrollers.count-1]==self) {

                                    //push方式

                                    returnNO;

                           }

                 }else{

                     //present方式

                    returnYES;

                }

         }

    returnNO;

    }

    将手势的执行和persentDriver数据更新链接起来后,UINaviagtionControllerDelegate和UIViewControllerTransitioningDelegate

    协议中返回的_persentDriver才可以带有手势的执行比例,这样动画就可以跟着手指滑动的程度来更新了。

    相关文章

      网友评论

          本文标题:ios 转场动画的制作

          本文链接:https://www.haomeiwen.com/subject/pxsuwttx.html