最近在学习苹果的transition转场动画,写一篇文章来记录一下实现转场动画的基本步骤。
iOS7以后,苹果为视图跳转单独提供了一整套的动画处理。原理我就不说了,网上一搜一大堆的,我主要说一下实现转场动画的具体步骤。
一、TestViewController.m
1、在跳转控制器中遵守<UIViewControllerTransitioningDelegate,UINavigationControllerDelegate>协议
2、实现<UIViewControllerTransitioningDelegate,UINavigationControllerDelegate>的协议方法,在其中返回一个遵守<UIViewControllerAnimatedTransitioning>协议的对象,在此对象中实现所需要的transition转场动画
3、跳转到toViewController,可用storyboard跳转,segue可以是modal或者push
4、设置toViewController的transitioningDelegate = TestViewController
TestViewController.m
#import "TestViewController.h"
#import "TestTwoViewController.h"
#import "BouncePresentAnimation.h"
#import "CoustomAnimator.h"
@interface TestViewController ()<UIViewControllerTransitioningDelegate,UINavigationControllerDelegate>// 1、遵守协议
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.delegate = self;
// Do any additional setup after loading the view.
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:@"Show TwoVC View"]) {
TestTwoViewController *twoVC = segue.destinationViewController;
twoVC.transitioningDelegate = self;// 4、设置TestTwoViewController的delegate
}
}
-(IBAction)actNextVC:(id)sender{
[self performSegueWithIdentifier:@"Show TwoVC View" sender:self];// 3、实现跳转到TestTwoViewController,segue可以设置modal和push两种
}
// 2、实现<UIViewControllerTransitioningDelegate,UINavigationControllerDelegate>的协议方法
#pragma mark- UIViewControllerTransitioningDelegate
// present
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
BouncePresentAnimation *animate = [[BouncePresentAnimation alloc] init];
animate.isPresenting = YES;
return animate;
}
// dismiss
-(id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController*)dismissed{
BouncePresentAnimation *animate = [[BouncePresentAnimation alloc] init];
animate.isPresenting = YES;
return animate;
}
#pragma mark- UINavigationControllerDelegate
// push pop
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController*)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC{
if (operation == UINavigationControllerOperationPush) {
// push
BouncePresentAnimation *animate = [[BouncePresentAnimation alloc] init];
animate.isPresenting = YES;
return animate;
}else{
// pop
BouncePresentAnimation *animate = [[BouncePresentAnimation alloc] init];
animate.isPresenting = NO;
return animate;
}
}
@end
二、CoustomAnimator.m 遵守<UIViewControllerAnimatedTransitioning>协议,实现协议的两个方法(动画时间和动画步骤)
CoustomAnimator.m
#import "CoustomAnimator.h"
@implementation BouncePresentAnimation
// 动画时间
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.9f;
}
// 动画内容
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
if (self.isPresenting) {
[self transitionForPresenting:transitionContext];
}else{
[self transitionForDismiss:transitionContext];
}
}
-(void)transitionForPresenting:(id <UIViewControllerContextTransitioning>)transitionContext{
// 可以看做为destination ViewController
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// 可以看做为source ViewController
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
// 添加toView到容器上
// 如果是XCode6 就可以用这段
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
// iOS8 SDK 新API
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
//UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
[[transitionContext containerView] addSubview:toView];
}else{
// 添加toView到容器上
[[transitionContext containerView] addSubview:toViewController.view];
}
// 如果是XCode5 就是用这段
[[transitionContext containerView] addSubview:toViewController.view];
toViewController.view.alpha = 0.0;
//只有当fromViewController.view在最前面时给fromViewController.view添加动画才有效果,设置toViewController.view.alpha = 0.0;或者[[transitionContext containerView] sendSubviewToBack:toViewController.view];
[UIView transitionWithView:fromViewController.view duration:0.9options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
toViewController.view.alpha = 1.0;
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
// [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
// // 动画效果有很多,这里就展示个左偏移
// fromViewController.view.transform = CGAffineTransformMakeTranslation(-[UIScreen mainScreen].bounds.size.width, 0);
// toViewController.view.alpha = 1.0;
// } completion:^(BOOL finished) {
// fromViewController.view.transform = CGAffineTransformIdentity;
// // 声明过渡结束-->记住,一定别忘了在过渡结束时调用 completeTransition: 这个方法
// [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
// }];
}
-(void)transitionForDismiss:(id<UIViewControllerContextTransitioning>)transitionContext{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *containerView = [[UIApplication sharedApplication] keyWindow];
CGRect frame = containerView.bounds;
frame.origin.y = - CGRectGetHeight(frame);
toViewController.view.userInteractionEnabled = YES;
[transitionContext.containerView addSubview:toViewController.view];
[transitionContext.containerView addSubview:fromViewController.view];
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
fromViewController.view.frame = frame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
@end
下面具体说一下CoustomAnimator.m中实现动画具体内容这个方法
-(void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
在这个方法中提供了一个transitionContext,通过这个transitionContext可以拿到一个containerView,一个FromViewController以及一个ToviewController,这个containerView相当于一个画板,FromViewController.view和ToviewController.view都可以add到containerView上面,然后就可以在这三个view上实现各种各样的动画效果了。需要注意的是ToviewController.view要设置为透明或者不在最上面的一层才能看到动画效果,因为刚开始的时候我们看到的是FromViewController的view,所以FromViewController.view必须在最上面一层开始动画才有效果