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;
}


複製代碼
相關文章
相關標籤/搜索