美文网首页
自定义转场动画 push--pop动画

自定义转场动画 push--pop动画

作者: TeeMo_Yan | 来源:发表于2018-11-24 00:07 被阅读10次

    思路:

    控制器A 控制器B 中各有一个圆形按钮,点击A中白色按钮会Push到B控制器

    自定义动画部分 创建动画类继承NSObject遵循UIViewControllerAnimatedTransitioning协议,实现以下方法

    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext;

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

    计算小圆和大圆的圆心和半径,用CABasicAnimation 绘制路径动添加画即可

    CABasicAnimation *anim = [CABasicAnimation animation];

    anim.fromValue = (id)smallPath.CGPath;

    anim.toValue = bigPath;

    A B控制器都要遵循UINavigationControllerDelegate 代理和实现以下方法  -(id)navigationController:(UINavigationController*)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController*)fromVC toViewController:(UIViewController*)toVC{

    //事例

    A B控制器都要遵循UINavigationControllerDelegate 代理和实现以下方法

    - (id)navigationController:(UINavigationController*)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController*)fromVC toViewController:(UIViewController*)toVC{

        if (operation == UINavigationControllerOperationPush) {

            TMTransition *trans = [TMTransition new];

            trans.isPush=YES;

            returntrans;

        }else{

            returnnil;

        }

    }

    //在此方法中实现具体的转场动画

    - (void)animateTransition:(id)transitionContext{

        //1.持有上下文

        _context= transitionContext;

        //2.获取一个view的容器

        UIView*containerView = [transitionContextcontainerView];

        //3.获取tovc的view,然后添加到容器里面

        UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

        //4.添加动画

        UIButton*btn;

        ViewController *VC1;

        TMBlueController *VC2;

        if(_isPush) {

            VC1 = [transitionContextviewControllerForKey:UITransitionContextFromViewControllerKey];

            VC2 = [transitionContextviewControllerForKey:UITransitionContextToViewControllerKey];

            btn = VC1.mFirstBtn;

        }else{

            VC2 = [transitionContextviewControllerForKey:UITransitionContextFromViewControllerKey];

            VC1 = [transitionContextviewControllerForKey:UITransitionContextToViewControllerKey];

            btn = VC2.mBlueBtn;

        }

        [containerViewaddSubview:VC1.view];

        [containerViewaddSubview:VC2.view];

        //5.画一个小圆(大小圆的中心点是一样)

        UIBezierPath *smallPath = [UIBezierPath bezierPathWithOvalInRect:btn.frame];

        //6.中心点

        CGPointcenterP;

        centerP = btn.center;

        //7.求大圆的半径

        CGFloatradius;

        //8.判断按钮在哪个象限

        CGFloat y = CGRectGetHeight(toVC.view.frame)-btn.center.y;

        CGFloat x = CGRectGetWidth(toVC.view.frame) - btn.center.x;

        if (btn.frame.origin.x > CGRectGetWidth(toVC.view.frame)/2) {

            if (btn.frame.origin.y < CGRectGetHeight(toVC.view.frame)/2) {

                //1

                radius =sqrtf(btn.center.x*btn.center.x+ y*y);

            }else{

                //4

                radius =sqrtf(btn.center.x*btn.center.x+ btn.center.y*btn.center.y);

            }

        }else{

            if (CGRectGetMaxY(btn.frame) < CGRectGetHeight(toVC.view.frame)/2) {

                //2

                radius =sqrtf(x*x + y*y);

            }else{

                //3

                radius =sqrtf(btn.center.y*btn.center.y+ x*x);

            }

        }

        //9.用贝塞尔画大圆

        UIBezierPath *bigPath = [UIBezierPath bezierPathWithArcCenter:centerP radius:radius startAngle:0 endAngle:M_PI*2 clockwise:YES];

        //10.把path添加到layer

        CAShapeLayer *shapeLayer = [CAShapeLayer layer];

        if(_isPush) {

            shapeLayer.path= bigPath.CGPath;

        }else{

            shapeLayer.path= smallPath.CGPath;

        }

        //11.蒙板

        UIViewController *VC;

        if(_isPush) {

            VC = [transitionContextviewControllerForKey:UITransitionContextToViewControllerKey];

        }else{

            VC = [transitionContextviewControllerForKey:UITransitionContextFromViewControllerKey];

        }

        VC.view.layer.mask= shapeLayer;

        //12.动画

        CABasicAnimation *anim = [CABasicAnimation animation];

        anim.keyPath=@"path";

        if(_isPush) {

            anim.fromValue= (id)smallPath.CGPath;

        }else{

            anim.fromValue= (id)bigPath.CGPath;

        }

        //    anim.toValue = bigPath;

        anim.delegate=self;

        [shapeLayeraddAnimation:animforKey:nil];

    }

    #pragma mark - CAAnimationDelegate

    - (void)animationDidStop:(CAAnimation*)anim finished:(BOOL)flag{

        [_context completeTransition:YES];

        UIViewController *VC;

        if(_isPush) {

            VC = [_context viewControllerForKey:UITransitionContextToViewControllerKey];

        }else{

            VC = [_context viewControllerForKey:UITransitionContextFromViewControllerKey];

        }

        VC.view.layer.mask = nil;

    }

    完整demo:

    https://github.com/TeeMoYan/TransitionDemo.git

    相关文章

      网友评论

          本文标题:自定义转场动画 push--pop动画

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