美文网首页首页投稿(暂停使用,暂停投稿)
自定义转场动画 push 和 pop (顺带看看present

自定义转场动画 push 和 pop (顺带看看present

作者: 浮桥小麦 | 来源:发表于2016-06-23 16:53 被阅读704次
不废话直接上代码,我们首先新建个工程,然后再创建一个控制器,分别给两个控制器设置两个背景色吧
  • 说明:我们的转场自定义动画的代码是写在单独创建的工具类里面的,先看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转场效果了
  • 接下来我们写个pop动画的工具类
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 转场
  • 网上有很多炫酷的转场效果,感兴趣可以自己去借鉴学习,不过任何困难的东西都是从基础来的,所以懂得基础原理还是很重要的

相关文章

网友评论

    本文标题:自定义转场动画 push 和 pop (顺带看看present

    本文链接:https://www.haomeiwen.com/subject/xhtodttx.html