不废话直接上代码,我们首先新建个工程,然后再创建一个控制器,分别给两个控制器设置两个背景色吧
- 说明:我们的转场自定义动画的代码是写在单独创建的工具类里面的,先看push的
TransPushTool.h
#import <UIKit/UIKit.h>//首先把这个头文件要从#import <Foundation/Foundation.h>改为UIKit的
//这里是要遵守这个动画转场的协议
@interface TransPushTool : NSObject<UIViewControllerAnimatedTransitioning>
@end
TransPushTool.m
@implementation TransPushTool
//遵守那个协议后,我们有两个必须实现的方法,在这里面来写你自己想要的动画方式
#返回转场动画执行时间
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 2;
}
#利用转场上下文写动画
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
/**<#文档注释#>***
1.transitionContext:转场上下文
2.fromVc:来自哪个ViewController
3.toVc:去哪个控制器
**/
//获取view(根据key获取view)
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
#我们push动画中用不到fromView
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
#动画的容器:所有设置的view都必须添加到这里面来
UIView *containerView = [transitionContext containerView];
//让要呈现的view透明度为0
toView.alpha = 0;
[containerView addSubview:toView];
#写动画(动画时间和上面的转场的时间必须一样)
[UIView animateWithDuration:2.0 animations:^{
toView.alpha = 1;
} completion:^(BOOL finished) {
//转场完成
[transitionContext completeTransition:YES];
}];
}
#至此在这个工具类中我们做的配置已写完了
#首先在那个ViewController.m文件中导入那个push动画工具类和下一个viewController头文件
//我们是自定义push动画,所以要给viewController加上导航控制器哦(再遵守导航控制器的协议)
@interface ViewController ()<UINavigationControllerDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
//设置导航控制器的代理
self.navigationController.delegate = self;
}
//转场按钮(在storyboard中拖一个按钮)
- (IBAction)pushBtn {
//正常的push转场就好
DetalViewController *vc = [[DetalViewController alloc]init];
[self.navigationController pushViewController:vc animated:YES];
}
#pragma mark -- 实现导航控制器的代理方法
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
//判断当前是push还是pop
if (operation == UINavigationControllerOperationPush)
{
return [[TransPushTool alloc]init];
}else
#如果我们写了pop的动画工具类的话,这里就填pop的
return nil;
}
#到这里就可以实现那个渐变出来的push转场效果了
TransPopTool.h
#import <UIKit/UIKit.h>
//遵守协议
@interface TransPopTool : NSObject<UIViewControllerAnimatedTransitioning>
TransPopTool.m
#import "TransPopTool.h"
@implementation TransPopTool
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 2;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
//获取view
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
//给toView的形变属性设值(缩小一点点)
toView.transform = CGAffineTransformMakeScale(0.9, 0.9);
UIView *containerView = [transitionContext containerView];
//将toView加到FromView之下
[containerView insertSubview:toView belowSubview:fromView];
//动画
[UIView animateWithDuration:2 animations:^{
//把来自的view放到屏幕下面去
fromView.center = CGPointMake(fromView.center.x, [UIScreen mainScreen].bounds.size.height * 2);
//将这个恢复其形变属性
toView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[fromView removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}
#方法和push写动画是一样的,我们怎么实现呢
//只需在viewControll中将导航控制器的代理方法那里改为
//判断当前是push还是pop
if (operation == UINavigationControllerOperationPush)
{
return [[TransPushTool alloc]init];
}else
return [[TransPopTool alloc]init];
}
接下来我们看看那个present 和 dismiss 的转场该怎么写
- 首先我们这两个工具类是不用动的,我们只需在下个控制器中设置一下代码就好(可以把导航的注释掉吧)
#在要present出来的控制器的.m文件中
#import "DetalViewController.h"
//导入那两个工具类的头文件(名字可以忽略哈)
#import "TransPushTool.h"
#import "TransPopTool.h"
//遵守这样的一个协议
@interface DetalViewController ()<UIViewControllerTransitioningDelegate>
@end
@implementation DetalViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置代理
self.transitioningDelegate = self;
}
#点击屏幕dismiss到上一个控制器
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark -- 实现那个present和dismiss的代理方法
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return [[TransPushTool alloc]init];
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
return [[TransPopTool alloc]init];
}
在viewController中我们来个present就好
//转场按钮
- (IBAction)pushBtn {
DetalViewController *vc = [[DetalViewController alloc]init];
[self presentViewController:vc animated:YES completion:nil];
}
总结:上面是很简单的自定义转场动画的两种方式,你会发现只要把转场的两个工具类封装起来,以后你的push 和 pop 还有present,dismiss 都可以用了。在push 和 pop 的自定义动画工具类可以写成一个工具类的,只需判断一下是push 还是 pop 转场
- 网上有很多炫酷的转场效果,感兴趣可以自己去借鉴学习,不过任何困难的东西都是从基础来的,所以懂得基础原理还是很重要的