您的位置:首页 > 移动开发 > IOS开发

iOS 转场动画笔记

2016-05-04 14:40 381 查看
文章转载出自:http://www.kittenyang.com/magicmove/

详细实现步骤在原文有说明

简单的说:导航的转场动画主要的实现原理步骤

1.创建2个动画过度Animated Transition对象(push一个效果+pop一个效果)NSObject实现UIViewControllerAnimatedTransitioning协议
主要重写2个协议方法

    a.- (void)animateTransition:(id
<UIViewControllerContextTransitioning>)transitionContext//动画时间

    b.- (NSTimeInterval)transitionDuration:(id
<UIViewControllerContextTransitioning>)transitionContext//两个页面的动画效果处理

2.VC里面实现UINavigationControllerDelegate代理重写1个协议方法

   a.- (id
<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController
*)navigationController

                                   animationControllerForOperation:(UINavigationControllerOperation)operation

                                                fromViewController:(UIViewController *)fromVC

                                                  toViewController:(UIViewController *)toVC

先看效果




1.构建过度动画

转场动画的自定义的精髓在于动画过度对象 - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext协议里面
可以获取到FromVC 和 ToVC 然后再在VC暴露属性出来做相应的alpha frame 等动画  之前要创建2个过渡动画对象 

一个是push

MagicMoveTransition
一个是pop

MagicMoveInverseTransition
原理都是一样 只是动画要自定义 有区别

例子:

//
//  MagicMoveTransition.m
//  KYMagicMove
//
//  Created by Kitten Yang on 1/17/15.
//  Copyright (c) 2015 Kitten Yang. All rights reserved.
//

#import "MagicMoveTransition.h"
#import "FirstCollectionViewController.h"
#import "SecondViewController.h"
#import "CollectionViewCell.h"
#import "UIView+MotionBlur.h"

@implementation MagicMoveTransition

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext{
return 0.25f;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
//获取两个VC 和 动画发生的容器
FirstCollectionViewController *fromVC = (FirstCollectionViewController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
SecondViewController *toVC   = (SecondViewController *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *containerView = [transitionContext containerView];

//对Cell上的 imageView 截图,同时将这个 imageView 本身隐藏
CollectionViewCell *cell =(CollectionViewCell *)[fromVC.collectionView cellForItemAtIndexPath:[[fromVC.collectionView indexPathsForSelectedItems] firstObject]];

UIView * snapShotView = [cell.imageView snapshotViewAfterScreenUpdates:NO];
snapShotView.frame = fromVC.finalCellRect = [containerView convertRect:cell.imageView.frame fromView:cell.imageView.superview];
cell.imageView.hidden = YES;

//设置第二个控制器的位置、透明度
toVC.view.frame = [transitionContext finalFrameForViewController:toVC];
toVC.view.alpha = 0;
toVC.imageViewForSecond.hidden = YES;

//把动画前后的两个ViewController加到容器中,顺序很重要,snapShotView在上方
[containerView addSubview:toVC.view];
[containerView addSubview:snapShotView];

//动起来。第二个控制器的透明度0~1;让截图SnapShotView的位置更新到最新;
[containerView layoutIfNeeded];
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
//        [containerView layoutIfNeeded];
toVC.view.alpha = 1.0;
snapShotView.frame = [containerView convertRect:toVC.imageViewForSecond.frame fromView:toVC.view];
} completion:^(BOOL finished) {
//为了让回来的时候,cell上的图片显示,必须要让cell上的图片显示出来
toVC.imageViewForSecond.hidden = NO;
cell.imageView.hidden = NO;
[snapShotView removeFromSuperview];
//告诉系统动画结束
[transitionContext completeTransition:!transitionContext.transitionWasCancelled];
}];

}

@end


之后的动画可以自己定义做更优美的动画 以上是我稍微修改了原文作者kitten-yang的源码

2.使用:

FromVC里面的在viewDidAppear设置self.navigationController.delegate =self;(否则pop回来第二次push触发不到协议)
然后实现协议方法

 
#pragma mark <UINavigationControllerDelegate>
- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{

if ([toVC isKindOfClass:[SecondViewController class]])
{
MagicMoveTransition *transition = [[MagicMoveTransition alloc]init];
return transition;
}
else
{
return nil;
}
}
ToVC里面也需要设置self.navigationController.delegate = self但是不要像FromVC一样在viewDidAppear

#pragma mark <UINavigationControllerDelegate>
- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC{
if ([toVC isKindOfClass:[FirstCollectionViewController class]])
{
MagicMoveInverseTransition *inverseTransition = [[MagicMoveInverseTransition alloc]init];
return inverseTransition;
}
else
{
return nil;
}
}

源码地址:https://github.com/Jacky-LinPeng/MegicMove   

特别说明一下: 以上的源码是我修改kitten-yang的源码 主要的代码还是kitten-yang的成果 因为很喜欢这个效果 所以写这个笔记 备忘
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  导航 ios 转场动画