iOS自定义转场动画

iOS7推出了新的转场动画API,以协议id<UIViewControllerInterativeTransition>、id<UIViewAnimatedTransitioning>方式开放给开发者,不一样于代理、类别,这样更易于咱们自定义动画,更加灵活。下面介绍一下自定义转场动画


自定义转场动画步骤:bash

1:建立动画管理类ZZFTransition,实现UIViewControllerAnimatedTransitioning,CAAnimationDelegate协议

自定义动画的主要代码都在管理类中实现,在须要动画的时候调用这个类的方法便可。动画

ZZFTransition.hui

#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>

typedef NS_ENUM(NSUInteger, ZZFTransitionType) {    ZZFTransitionTypePush,    ZZFTransitionTypePop,};

@interface ZZFTransition : NSObject<UIViewControllerAnimatedTransitioning,CAAnimationDelegate>+(ZZFTransition *)transitionAnimationWithType:(ZZFTransitionType)type;@end复制代码


定义枚举类型ZZFTransitionType,包含两个值,分别是push类型和pop类型。spa

定义类方法transitionAnimationWithType,传入动画类型,返回实例对象。代理

ZZFTransition.mcode

+(ZZFTransition *)transitionAnimationWithType:(ZZFTransitionType)type{
    ZZFTransition *transition = [[ZZFTransition alloc]init];
    transition.type = type;
    return transition;
}


复制代码


在.m文件中实现transitionAnimationWithType类方法,初始化实例对象,设置动画类型,返回对象。cdn

2:实现UIViewControllerAnimatedTransitioning协议中的方法

-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 3;
}
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    
    self.transitionContext = transitionContext;
    
    switch (_type) {
        case ZZFTransitionTypePush:
        {
            [self pushAnimation:transitionContext];
        }
            break;
            
        case ZZFTransitionTypePop:
        {
            [self popAnimation:transitionContext];
        }
            break;
    }
}


复制代码


-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext;这个方法返回转场动画执行的时间。对象

-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext;在这个方法内部实现动画的主要代码。开发

这里根据建立管理对象的时候传进来的动画类型,来分别处理不一样的动画逻辑。把push和pop的动画实现放到一个方法中去,这里的代码更简洁。animation

- (void)pushAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
    // 得到即将消失的vc的v
    UIView *fromeView = [transitionContext viewForKey:UITransitionContextFromViewKey];
    // 得到即将出现的vc的v
    UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
    // 得到容器view
    UIView *containerView = [transitionContext containerView];
    [containerView addSubview:fromeView];
    [containerView addSubview:toView];
    UIBezierPath *startBP = [UIBezierPath bezierPathWithOvalInRect:CGRectMake((containerView.frame.size.width)/2, (containerView.frame.size.height)/2, 12, 12)];
    CGFloat radius = containerView.frame.size.height - 100;
    UIBezierPath *finalBP = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(150 - radius, 150 -radius, radius*2, radius*2)];
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.path = finalBP.CGPath;
    toView.layer.mask = maskLayer;
    //执行动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
    animation.fromValue = (__bridge id _Nullable)(startBP.CGPath);
    animation.toValue = (__bridge id _Nullable)(finalBP.CGPath);
    animation.duration = [self transitionDuration:transitionContext];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.delegate = self;
    [maskLayer addAnimation:animation forKey:@"path"];
}


复制代码


参数transitionContext是执行动画的上下文,里面包含动画执行所须要的全部元素。

经过键值的方式,从上下文对象中能够的到须要执行动画的上一个VC和view,下一个VC和view。

UITransitionContextFromViewKey  即将消失的view

UITransitionContextToViewKey  即将出现的view

UITransitionContextFromViewControllerKey  即将消失的控制器

UITransitionContextToViewControllerKey  即将出现的控制器

而后经过上下文的containerView方法能够获得一个容器view,全部的动画都是在这个容器view内进行的,因此须要把fromView和toView都加入到containerView中。

下边用贝塞尔曲线画两个圆,而后用CABasicAnimation执行从小圆到大圆的动画。

到这里一个自定义的push动画就完成了,下边是使用的方法。

3:自定义动画的使用

在须要执行自定义动画的控制器中,遵照UINavigationControllerDelegate协议,并实现-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC;代理方法。

在执行push或pop操做时,这个代理方法会回调,在方法内部拿到跳转的动画类型,而后执行本身的动画代码就能够实现自定义转场动画。

-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
    if (operation == UINavigationControllerOperationPush) {
        ZZFTransition *pushTranstion = [ZZFTransition transitionAnimationWithType:ZZFTransitionTypePush];
        return pushTranstion;
    }
    return nil;
}

复制代码


这里只实现了push,要实现pop自定义动画,同理。

4:注意点

执行push动画后,能够发现一个问题,界面的全部交互失效了,是由于执行动画时控制器view上加了遮罩layer,在动画执行完成后把遮罩去掉就能够了。

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
        [self.transitionContext completeTransition:YES];
    //清除相应控制器视图的mask
    [self.transitionContext viewForKey:UITransitionContextFromViewKey].layer.mask = nil;
    [self.transitionContext viewForKey:UITransitionContextToViewKey].layer.mask = nil;
}


复制代码
相关文章
相关标签/搜索