iOS 转场动画
首先看一个简单的 效果图
模拟器不知道怎么了 变得这么慢,就将就着看吧
转场动画.gif
关于转场动画我们主要考虑两个,一个是导航条中的 转场就是(push、pop) ,另外一个就是 present 和dismiss
1. push、pop 的转场
关于push 和 pop 我们首先要先设置self.navigationController.delegate = self; (这个self 就是 VC控制器),然后我们找到这个导航条的代理
- (id<UIViewControllerAnimatedTransitioning>) navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
if (operation == UINavigationControllerOperationPush) {
return _pushAnimation;
}else if (operation == UINavigationControllerOperationPop) {
return _popAnimation;
}else{
return nil;
}
}
这里面的_pushAnimation 和 _popAnimation是我接下来需要讲的动画。
PushAnimation 的设置 (PopAnimation 其实也是一样)
这里首先要 实现 UIViewControllerAnimatedTransitioning 这个ios7 以后的一个代理,然后我们找到这个delegate 中的两个必须实现的方法 1.- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext 显然这个是返回动画时间的代理;- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext,就是把一些动画的交互写在这里
//
// PushAnimation.h
// 转场动画
//
// Created by apple on 16/6/22.
// Copyright © 2016年 李重阳. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIViewControllerTransitioning.h>
@interface PushAnimation : NSObject<UIViewControllerAnimatedTransitioning>
@end
//
// PushAnimation.m
// 转场动画
//
// Created by apple on 16/6/22.
// Copyright © 2016年 李重阳. All rights reserved.
//
#import "PushAnimation.h"
@implementation PushAnimation
/* 动画持续的时间 **/
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
return 1.0;
}
/*动画交互 **/
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
//目的ViewController
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//起始ViewController
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
//添加toView到上下文的视图中
UIView * containerView = [transitionContext containerView];
/* 加入 目的 控制器的View**/
[containerView addSubview:toViewController.view];
[containerView bringSubviewToFront:fromViewController.view];
//自定义动画
toViewController.view.transform = CGAffineTransformMakeTranslation(-320, 0);
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
fromViewController.view.transform = CGAffineTransformMakeTranslation(320, 0);
toViewController.view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
fromViewController.view.transform = CGAffineTransformIdentity;
// 声明过渡结束时调用 completeTransition: 这个方法
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
@end
2. present 和dismiss 的转场
其实和pop 差不多 只不过有两点不同
1.控制器需要实现UIViewControllerTransitioningDelegate这个代理
2.就是在转场的时候 当dismiss 的时候 要UIView * snapshotView = [fromViewController.view snapshotViewAfterScreenUpdates:YES];截个 源控制器的屏,可能是因为dismiss 后源控制器马上释放掉了。
- (IBAction)present:(id)sender {
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ViewController3 * vc3 = [storyboard instantiateViewControllerWithIdentifier:@"ViewController3"];
vc3.transitioningDelegate = self;
[self presentViewController:vc3 animated:YES completion:nil];
}
#pragma mark - UIViewControllerTransitioningDelegate
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
_presentOrDismissAnimation.animationType = AnimationTypePresent;
return _presentOrDismissAnimation;
}
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
_presentOrDismissAnimation.animationType = AnimationTypeDismiss;
return _presentOrDismissAnimation;
}
//
// PresentOrDismissAnimation.h
// 转场动画
//
// Created by apple on 16/6/22.
// Copyright © 2016年 李重阳. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef enum {
AnimationTypePresent,
AnimationTypeDismiss
} AnimationType;
@interface PresentOrDismissAnimation : NSObject<UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign) AnimationType animationType;
@end
//
// PresentOrDismissAnimation.m
// 转场动画
//
// Created by apple on 16/6/22.
// Copyright © 2016年 李重阳. All rights reserved.
//
#import "PresentOrDismissAnimation.h"
@implementation PresentOrDismissAnimation
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
return 3;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
//目的ViewController
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
//起始ViewController
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
//添加toView到上下文的视图中
UIView * containerView = [transitionContext containerView];
[containerView addSubview:toViewController.view];
if (self.animationType == AnimationTypePresent) {
toViewController.view.transform = CGAffineTransformMakeTranslation(0, -568);
//进行动画
[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0
usingSpringWithDamping:.5
initialSpringVelocity:.6
options:UIViewAnimationOptionCurveLinear
animations:^{
toViewController.view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}else {
/* dismiss 的时候 fromView 会马上消失掉了,所以先截个屏幕**/
UIView * snapshotView = [fromViewController.view snapshotViewAfterScreenUpdates:YES];
[transitionContext.containerView addSubview:snapshotView];
//进行动画
[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0
usingSpringWithDamping:0.5
initialSpringVelocity:0
options:UIViewAnimationOptionCurveLinear
animations:^{
snapshotView.transform = CGAffineTransformMakeTranslation(0, 568);
} completion:^(BOOL finished) {
[snapshotView removeFromSuperview];
//结束Transition
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
}
@end