iOS ~ ViewController的Push,Pop和Pr

作者: SSBun | 来源:发表于2016-08-29 14:11 被阅读3848次

    转场动画涉及到的包括导航控制器的Push动画和Pop动画,以及普通控制器的Present和Dismiss动画,主要就是通过控制器遵守UIViewControllerTransitioningDelegate,并实现对应的方法,返回一个遵守UIViewControllerAnimatedTransitioning协议的对象,而主要的动画实现就是写在这个对象当中~

    • __ 如果是Push和pop动画需要再push控制器和pop时的控制器里同时实现导航控制器的代理以实现Push和Pop的动画,而Present和Dismiss动画只需要在Presnent的时候设置代理,并实现present和dismiss的协议方法就OK了 __
    • __ 为了方便使用,一般会封装代理返回的动画协议对象(UIViewControllerAnimatedTransitioning),通过之类来进一步处理各种各样的转场动画 __
    //
    //  ViewController.m
    //  transitionDemo
    //  Copyright © 2016年 SSBun. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "TwoViewController.h"
    #import "PushAnimator.h"
    #import "PresentAnimator.h"
    #import "DismissAnimator.h"
    
    @interface ViewController ()<UIViewControllerTransitioningDelegate,UINavigationControllerDelegate>
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        self.navigationController.delegate = self;
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        TwoViewController *twoVc = [[TwoViewController alloc] init];
        // Present
        twoVc.transitioningDelegate  = self;
        twoVc.modalPresentationStyle = UIModalPresentationCustom;
        [self presentViewController:twoVc
                           animated:YES
                         completion:^{
                         }];
        // Push
        // [self.navigationController pushViewController:twoVc animated:YES];
    }
    
    #pragma mark - 动画代理
    - (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                       animationControllerForOperation:(UINavigationControllerOperation)operation
                                                    fromViewController:(UIViewController *)fromVC
                                                      toViewController:(UIViewController *)toVC{
        
        if ([toVC isKindOfClass:[TwoViewController class]]) {
            
            PushAnimator *transition = [[PushAnimator alloc] init];
            return transition;
            
        }else{
            
            return nil;
        }
    }
    
    #pragma mark - 定制转场动画 (Present 与 Dismiss动画代理)
    - (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
                                                                      presentingController:(UIViewController *)presenting
                                                                          sourceController:(UIViewController *)source {
        
        // 推出控制器的动画
        return [PresentAnimator new];
    }
    
    - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
        
        DismissAnimator *dismissAnimator   = [DismissAnimator new];
        dismissAnimator.transitionDuration = 1.f;
        
        // 退出控制器动画
        return dismissAnimator;
    }
    
    @end
    

    __ 可以看出协议方法主要时返回了一个遵守<UIViewControllerAnimatedTransitioning>协议的对象,所以主要的重点在实现这个对象上 __

    //  BaseAnimator.h
    
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface BaseAnimator : NSObject <UIViewControllerAnimatedTransitioning>
    
    /**
     *  动画执行时间(默认值为0.5s)
     */
    @property (nonatomic) NSTimeInterval  transitionDuration;
    
    /**
     *  == 子类重写此方法实现动画效果 ==
     *
     *  动画事件
     */
    - (void)animateTransitionEvent;
    
    /**
     *  == 在animateTransitionEvent使用才有效 ==
     *
     *  源头控制器
     */
    @property (nonatomic, readonly, weak) UIViewController *fromViewController;
    
    /**
     *  == 在animateTransitionEvent使用才有效 ==
     *
     *  目标控制器
     */
    @property (nonatomic, readonly, weak) UIViewController *toViewController;
    
    /**
     *  == 在animateTransitionEvent使用才有效 ==
     *
     *  containerView
     */
    @property (nonatomic, readonly, weak) UIView           *containerView;
    
    /**
     *  动画事件结束
     */
    - (void)completeTransition;
    
    @end
    
    //  BaseAnimator.m
    #import "BaseAnimator.h"
    
    @interface BaseAnimator ()
    
    @property (nonatomic, weak) id <UIViewControllerContextTransitioning> transitionContext;
    
    @property (nonatomic, weak) UIViewController  *fromViewController;
    @property (nonatomic, weak) UIViewController  *toViewController;
    @property (nonatomic, weak) UIView            *containerView;
    
    @end
    
    @implementation BaseAnimator
    
    #pragma mark - 初始化
    - (instancetype)init {
        
        self = [super init];
        if (self) {
        
            // 默认参数设置
            [self deafultSet];
        }
        
        return self;
    }
    
    - (void)deafultSet {
        
        _transitionDuration = 0.5f;
    }
    
    #pragma mark - 动画代理
    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
        
        return _transitionDuration;
    }
    
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
        
        self.fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        self.toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        self.containerView      = [transitionContext containerView];
        self.transitionContext  = transitionContext;
        
        [self animateTransitionEvent];
    }
    
    - (void)animateTransitionEvent {
        
        /* == 代码示例 ==
         
        UIView *tmpView  = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        [self.containerView addSubview:self.toViewController.view];
        [self.containerView addSubview:tmpView];
        
        [UIView animateWithDuration:self.transitionDuration
                              delay:0.0f
             usingSpringWithDamping:1 initialSpringVelocity:0.f options:0 animations:^{
                 
                 tmpView.frame = CGRectMake(0, 0, 100, 100);
                 
             } completion:^(BOOL finished) {
                 
                 [tmpView removeFromSuperview];
                 [self completeTransition];
             }];
         */
    }
    
    #pragma mark -
    - (void)completeTransition {
    
        [self.transitionContext completeTransition:!self.transitionContext.transitionWasCancelled];
    }
    
    @end
    

    __ 其中的fromViewController就是准备跳转的控制器,toViewController 就是要跳转到的控制器,containerView是整个动画的画布,需要将要跳转到的控制器的view添加到画布上执行动画,而在animateTransitionEvent中就时具体实现动画的过程了,不要忘了还要返回动画时间,用起来的时候就看各自的发挥了,可以编写子类来实现这个方法~ __

    相关文章

      网友评论

      • 阿兹尔:有没有Demo #import "PushAnimator.h"
        #import "PresentAnimator.h"
        #import "DismissAnimator.h" 这几个?

      本文标题:iOS ~ ViewController的Push,Pop和Pr

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