iOS自定义转场动画

来源:互联网 发布:华泰交易软件下载 编辑:程序博客网 时间:2024/05/01 23:16

自定义转场动画主用到3个类

  • 实现UIViewControllerAnimatedTransitioning协议的动画类
  • 继承UIPercentDrivenInteractiveTransition类的手势类
  • 实现UIViewControllerContextTransitioning协议的transitionContext

先实现present和dismiss动画

PresentedViewController *vc = [[PresentedViewController alloc] init];//设置动画的代理,vc需要实现UIViewControllerTransitioningDelegate协议vc.transitioningDelegate = vc;[self presentViewController:vc animated:YES completion:NULL];

UIViewControllerTransitioningDelegate协议里方法主要用到一下四个方法

//返回present的动画实例- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;//返回dismiss的动画实例- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;//返回present动画手势实例- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator;//返回dismiss动画手势实例- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator;

这里主要介绍dismiss的动画和手势
我们建立了一个动画类SunAimator,实现了UIViewControllerAnimatedTransitioning协议,下面是协议两个方法的实现

- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext {    //动画时间    return 1.5;}- (void)dismissAnimatorTransition:(id <UIViewControllerContextTransitioning>)transitionContext {    //将要消失的视图    UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];    //将要显示的视图    UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];    //动画过程的背景视图    UIView *containerView = [transitionContext containerView];    //动画时间    NSTimeInterval duration = [self transitionDuration:transitionContext];    //应为要在fromView上做动画,为了一些不必要的麻烦这里采用截图处理    UIView *tempView = [self snapWithView:fromView];    //将参与动画的视图添加到动画背景视图上    [containerView addSubview:toView];    [containerView addSubview:tempView];    //动画的具体内容,也可自自己使用CABasicAnimation、CAKeyframeAnimation和CAKeyframeAnimation实现更复杂的动画    [UIView animateWithDuration:duration animations:^{        CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);        tempView.transform = transform;    } completion:^(BOOL finished) {        //判断手势是否失败        if([transitionContext transitionWasCancelled]){            //发送一个失败的消息            [transitionContext completeTransition:NO];            //失败的话需要将目标视图移除,还要将原先的页面显示出来(显示很重要)            [toView removeFromSuperview];            [containerView addSubview:fromView];        }else{            [transitionContext completeTransition:YES];        }        //临时视图不管动画失败还是成功都要移除        [tempView removeFromSuperview];    }];}

下面是手势类SunDrivenInteractive,手势需要继承UIPercentDrivenInteractiveTransition类

SunDrivenInteractive.h@interface SunDrivenInteractive : UIPercentDrivenInteractiveTransition@property (nonatomic,assign) BOOL isIneractive;- (void)addGestureToViewCOntroller:(UIViewController *)fromVC;@end
SunDrivenInteractive.m#import "SunDrivenInteractive.h"@interface SunDrivenInteractive ()@property (nonatomic,weak) UIViewController *fromVC;@property (nonatomic,assign) CGFloat percent;@end@implementation SunDrivenInteractive- (void)addGestureToViewCOntroller:(UIViewController *)fromVC {    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveAction:)];    [fromVC.view addGestureRecognizer:panGesture];    _fromVC = fromVC;}- (void)moveAction:(UIPanGestureRecognizer *)panGesture {    if(panGesture.state == UIGestureRecognizerStateBegan){        _isIneractive = YES;        [_fromVC dismissViewControllerAnimated:YES completion:NULL];    }else if (panGesture.state == UIGestureRecognizerStateChanged){        CGFloat translationX = [panGesture translationInView:_fromVC.view].x;        if(translationX > 0){            _percent = translationX/300.0;            //更新进度            [self updateInteractiveTransition:_percent];        }    }else if (panGesture.state == UIGestureRecognizerStateEnded){        _isIneractive = NO;        if(_percent > 0.5){            [self finishInteractiveTransition];        }else{            [self cancelInteractiveTransition];        }    }}

动画类和手势类都已经准备好了,接下里是PresentedViewController.m里的实现

@interface PresentedViewController ()@property (nonatomic,strong) SunDrivenInteractive *interactive;@end@implementation PresentedViewController- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view.    self.view.backgroundColor = [UIColor yellowColor];    _interactive = [[SunDrivenInteractive alloc] init];    [_interactive addGestureToViewCOntroller:self];}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {    [self dismissViewControllerAnimated:YES completion:NULL];}#pragma mark - UIViewControllerTransitioningDelegate- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {    //present动画    return [[SunAimator alloc] initWithAnimatorType:(SunAimatorTypePresent)];}- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {    //dismiss动画    return [[SunAimator alloc] initWithAnimatorType:(SunAimatorTypeDismiss)];}- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator {    //present手势    return nil;}- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator {    //dismiss手势    return (_interactive.isIneractive?_interactive:nil);}

简单的转场动画就这样实现了
Demo地址

原创粉丝点击