自定义Push和Pop的动画效果

作者: 懒得起名的伊凡 | 来源:发表于2015-10-27 18:50 被阅读2520次

    先写一些通用部分

    实现协议

    在要添加自定义效果的视图控制器中实现代理协议UINavigationControllerDelegate

    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        self.navigationController.delegate = self;
    }
    

    实现代理方法

    #pragma mark -UINavigationControllerDelegate
    - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
    {
        if (operation == UINavigationControllerOperationPush) {
            //返回我们自定义的效果
            return [[PushTransition alloc]init];
        }
        else if (operation == UINavigationControllerOperationPop){
            return [[PopTransition alloc]init];
        }
        //返回nil则使用默认的动画效果
        return nil;
    }
    

    注:PushTransition、PopTransition为具体效果的实现

    PushTransition的实现

    这种效果的实现类需要实现UIViewControllerAnimatedTransitioning协议

    通用代码部分

    //.h
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface PushTransition : NSObject<UIViewControllerAnimatedTransitioning>
    
    @end
    
    //.m
    #import "PushTransition.h"
    
    @interface PushTransition ()
    
    @end
    
    @implementation PushTransition
    
    // This is used for percent driven interactive transitions, as well as for container controllers that have companion animations that might need to
    // synchronize with the main animation.
    - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext
    {
        //返回动画的执行时间
        return 1.0f;
    }
    // This method can only  be a nop if the transition is interactive and not a percentDriven interactive transition.
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
    {    
        self.transitionContext = transitionContext;
    
        UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        //不添加的话,屏幕什么都没有
        UIView *containerView = [transitionContext containerView];
        [containerView addSubview:fromVC.view];
        [containerView addSubview:toVC.view];
    
        //注意注意一定要注意这里。我们就是在这里添加我们所需要的动画效果。将动画效果的代码放在这里就行了。重要的事情要说好几遍
    
        //如果取消了就设置为NO,反之,设置为YES。如果添加了动画,这句代码在动画结束之后再调用
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }
    

    实例程序一

    实现了一个简单的扇形动画

    //.m
    #import "PushTransition.h"
    
    @interface PushTransition ()
    
    @property(nonatomic,strong) id<UIViewControllerContextTransitioning>transitionContext;
    
    @end
    
    @implementation PushTransition
    
    // This is used for percent driven interactive transitions, as well as for container controllers that have companion animations that might need to
    // synchronize with the main animation.
    - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext
    {
        return 1.0f;
    }
    // This method can only  be a nop if the transition is interactive and not a percentDriven interactive transition.
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
    {
        self.transitionContext = transitionContext;
    
        UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        //不添加的话,屏幕什么都没有
        UIView *containerView = [transitionContext containerView];
        [containerView addSubview:fromVC.view];
        [containerView addSubview:toVC.view];    
    CGRect originRect = CGRectMake(0, 0, 50, 50);
    
        UIBezierPath *maskStartPath = [UIBezierPath bezierPathWithOvalInRect:originRect];
        UIBezierPath *maskEndPath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(originRect, -2000, -2000)];
    
        //创建一个CAShapeLayer来负责展示圆形遮盖
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    //    maskLayer.path = maskEndPath.CGPath;//将他的path指定为最终的path,来避免在动画完成后回弹
    toVC.view.layer.mask = maskLayer;
    
        CABasicAnimation *maskAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
        maskAnimation.fromValue = (id)maskStartPath.CGPath;
        maskAnimation.toValue = (id)maskEndPath.CGPath;
        maskAnimation.duration = [self     transitionDuration:transitionContext];
        maskAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        maskAnimation.fillMode = kCAFillModeForwards;
        maskAnimation.removedOnCompletion = NO;
        maskAnimation.delegate = self;
        [maskLayer addAnimation:maskAnimation forKey:@"Path"];
    }
    
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
    {
        NSLog(@"搞定结束");
        [self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
        //去除mask
        [self.transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view.layer.mask = nil;
        [self.transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view.layer.mask = nil;
    }
    
    @end
    

    实例程序二

    实现从下方弹出的效果

    NSTimeInterval duration = [self transitionDuration:transitionContext];
    CGRect screenBounds = [[UIScreen mainScreen]bounds];
    CGRect finalFrame = [transitionContext finalFrameForViewController:toVC];
    toVC.view.frame = CGRectOffset(finalFrame, 0, screenBounds.size.height);
    
    [UIView animateWithDuration:duration delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
        toVC.view.frame = finalFrame;
    } completion:^(BOOL finished) {
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];

    相关文章

      网友评论

        本文标题:自定义Push和Pop的动画效果

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