自定義轉場動畫(二)

江楓夜雨發表於2017-03-05

之前介紹一篇文章 自定義轉場動畫(一),主要介紹了Present的轉場動畫。今天介紹一下有關Push的轉場動畫。

準備:首先要兩個UIViewController和一個繼承與UIPercentDrivenInteractiveTransition的類。

ViewController1

ViewController2

PushTransitionAnimator

PushTransitionAnimator
.h

@interface PushTransitionAnimator : UIPercentDrivenInteractiveTransition<UIViewControllerAnimatedTransitioning,UIViewControllerTransitioningDelegate,UIGestureRecognizerDelegate>

@property (nonatomic, assign) BOOL isPop;//是push還是pop

.m
完成UIViewControllerAnimatedTransitioning協議

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return self.transitionDuration;
}
//這裡實現從下往上的Push
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{

    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    self.targetViewController = toViewController;
    [self creatDragGesture];

    UIView *containerView = [transitionContext containerView];
    if (!self.isPop) {
        CGRect startRect;

        [containerView addSubview:toViewController.view];

        toViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        startRect = CGRectMake(0, CGRectGetHeight(containerView.bounds), CGRectGetWidth(containerView.bounds), CGRectGetHeight(containerView.bounds));

        toViewController.view.frame = startRect;

        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            fromViewController.view.alpha = self.behindViewAlpha;
            toViewController.view.frame = CGRectMake( 0, 0,
                                                     CGRectGetWidth(toViewController.view.frame),
                                                     CGRectGetHeight(toViewController.view.frame) );
        } completion:^(BOOL finished) {
            [fromViewController endAppearanceTransition];
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        }];

    }else{
        [containerView addSubview:toViewController.view];

        toViewController.view.alpha = self.behindViewAlpha;

        CGRect endRect;

        endRect = CGRectMake(0, CGRectGetHeight(fromViewController.view.frame), CGRectGetWidth(fromViewController.view.frame), CGRectGetHeight(fromViewController.view.frame));

        [toViewController beginAppearanceTransition:YES animated:YES];

        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            toViewController.view.alpha = 1.0f;
            fromViewController.view.frame = endRect;

        } completion:^(BOOL finished) {
            [toViewController endAppearanceTransition];
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        }];
    }
}

如何使用

Push與Present最直觀的區別就是有導航的參與。所以我們要在ViewController1中準守 UINavigationControllerDelegate 協議。

初始化 設定導航代理

- (void)viewDidLoad {
    [super viewDidLoad];
        _animator                    = [[PXPushTransitionAnimation alloc] initWithModalViewController:self];
    _animator.dragable           = YES;
    _animator.bounces            = YES;
    _animator.behindViewAlpha    = 0.3;
    _animator.transitionDuration = 0.35f;
    _animator.behindViewScale    = 1.0f;
    ....
}
- (void)viewDidAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.navigationController.delegate        = self;
}

實現代理方法

#pragma mark - **************** Navgation delegate
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                  animationControllerForOperation:(UINavigationControllerOperation)operation
                                               fromViewController:(UIViewController *)fromVC
                                                 toViewController:(UIViewController *)toVC
{
    if (operation == UINavigationControllerOperationPush) {
        self.animator.isPop = NO;//push
    }else if (operation == UINavigationControllerOperationPop){
        self.animator.isPop = YES;//pop
    }
    return self.animator;
}

有關手勢的返回互動可以參考present,原理相同。

相關文章