iOS - 自定义转场动画

经常在项目中 , 我们会用到一些下拉菜单 , 或者上弹菜单等 . 简单的做法就是加一层蒙板 , 自定义一个view , 写一下动画就完成了 . 但是这样写的话 , 首先是比较low , 其次是性能略有损耗 , 且比较杂乱 . 其实在iOS中 , 如果是iPad开发的 , 苹果直接就有提供PopoVerController使用 . 如果是iPhone呢 , 也可以通过重写类 , 来实现


#import "ViewController.h"
#import "MYShowAnimationController.h"
#import "MYPresentationController.h"


@interface ViewController ()<UIViewControllerTransitioningDelegate,UIViewControllerAnimatedTransitioning>

@property (assign, nonatomic) BOOL isOpen;
//下拉菜单控制器
@property (strong, nonatomic) MYShowAnimationController *showVc;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
    [button setTitle:@"开始动画" forState:UIControlStateNormal];
    button.frame = CGRectMake(275 *0.5,20,100, 44);
    [self.view addSubview:button];
    [button addTarget:self action:@selector(animationBegin) forControlEvents:UIControlEventTouchUpInside];

    self.navigationItem.titleView = button;
}


- (void)animationBegin
{

    if (!self.isOpen) {

    self.showVc = [[MYShowAnimationController alloc]init];
    //设定模态风格 , custom可以保持容器下层的图层不被隐藏
    self.showVc.modalPresentationStyle = UIModalPresentationCustom;

    self.showVc.transitioningDelegate = self;

    [self presentViewController:self.showVc animated:YES completion:^{

        self.isOpen = YES;
    }];

    }else{

    [self.showVc dismissViewControllerAnimated:YES completion:^{

        [self.showVc.view removeFromSuperview];
        self.showVc = nil;
//        self.isOpen = NO;

    }];
    }
}

//代理方法:改变弹出控制器view的frame
//返回自定义的容器控制器,我们自己来写它的布局
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
{
    return [[MYPresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting];
}


// UIViewControllerTransitioningDelegate 协议中方法 , 自定义弹出动画 , 返回一个遵循 UIViewControllerAnimatedTransitioning 协议的控制器
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    return self;
}

//消失动画
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    return self;
}

//动画持续时间
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
    return 0.25;
}

//获取转场上下文 , 拿到presentedView 和 presentingView自定义动画
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{


//    if (!self.isOpen) {
//
//        //根据key值取出被模态视图view
//        //   UITransitionContextToViewKey
//        //   UITransitionContextFromViewKey
//        UIView *presentedView = [transitionContext viewForKey:UITransitionContextToViewKey];
//
//        //设置锚点 (从顶点中心弹出)
//        presentedView.layer.anchorPoint = CGPointMake(0.5, 0);
//        
//        //添加被模态视图view到容器view中
//        [[transitionContext containerView]addSubview:presentedView];
//        NSLog(@"%@",presentedView);
//
//        //执行动画
//        presentedView.transform = CGAffineTransformMakeScale(1.0,0.001);
//        [UIView animateWithDuration:0.25 animations:^{
//            
//            presentedView.transform = CGAffineTransformIdentity;
//            
//        }
//                         completion:^(BOOL finished) {
//            
//            //告知动画已经执行完毕
//            [transitionContext completeTransition:YES];
//            self.isOpen = YES;
//        }];
//    }else{
//
//        UIView *presentingView = [transitionContext viewForKey:UITransitionContextFromViewKey];
//
//        //添加被模态视图view到容器view中
//        [[transitionContext containerView]addSubview:presentingView];
//
//        presentingView.transform = CGAffineTransformMakeScale(1.0,1.0);
//        //执行动画
//        [UIView animateWithDuration:0.25 animations:^{
//            
//            presentingView.transform = CGAffineTransformMakeScale(1.0,0.001);
//            
//        } completion:^(BOOL finished) {
//            
//            //告知动画已经执行完毕
//            [transitionContext completeTransition:YES];
//            self.isOpen = NO;
//            
//        }];
//    }



    if (!self.isOpen) {

        //根据key值取出被模态视图view
        //   UITransitionContextToViewKey
        //   UITransitionContextFromViewKey
        UIView *presentedView = [transitionContext viewForKey:UITransitionContextToViewKey];

        //设置锚点 (从顶点中心弹出)
        presentedView.layer.anchorPoint = CGPointMake(0.5, 0);

        //添加被模态视图view到容器view中
        [[transitionContext containerView]addSubview:presentedView];
        NSLog(@"%@",presentedView);

        //执行动画
//        presentedView.transform = CGAffineTransformMakeScale(1.0,0.001);

        presentedView.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - 200) *0.5, -300, 200, 300);
        [UIView animateWithDuration:0.25 delay:0.0 usingSpringWithDamping:0.2 initialSpringVelocity:5 options:UIViewAnimationOptionCurveEaseIn animations:^{

            presentedView.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - 200) *0.5, 0, 200, 300);

        } completion:^(BOOL finished) {

            [transitionContext completeTransition:YES];
            self.isOpen = YES;
        }];

    }else{

        UIView *presentingView = [transitionContext viewForKey:UITransitionContextFromViewKey];

        //添加被模态视图view到容器view中
        [[transitionContext containerView]addSubview:presentingView];

        [UIView animateWithDuration:0.25 animations:^{

            presentingView.transform = CGAffineTransformMakeScale(1.0, 0.001);
        } completion:^(BOOL finished) {

            [transitionContext completeTransition:YES];
            self.isOpen = NO;
        }];
    }
}

被模态类


#import "MYShowAnimationController.h"

@interface MYShowAnimationController ()

@end

@implementation MYShowAnimationController



- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor redColor];
 }

模态时 容器view控制器

#import <UIKit/UIKit.h>

//继承与 UIPresentationController
@interface MYPresentationController : UIPresentationController

@end

--------------------------------------------------------

#import "MYPresentationController.h"

@interface MYPresentationController ()
//蒙板
@property (strong, nonatomic) UIControl *coverView;

@end

@implementation MYPresentationController

//蒙板
- (UIControl *)coverView
{
    if (!_coverView) {
        _coverView = [[UIControl alloc]init];
        _coverView.frame = CGRectMake(0,0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
        _coverView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
        [_coverView addTarget:self action:@selector(coverTouch) forControlEvents:UIControlEventTouchUpInside];
    }
    return _coverView;
}


//容器view即将布局
- (void)containerViewWillLayoutSubviews
{
    [super containerViewWillLayoutSubviews];
    //调整容器view大小
    self.containerView.frame = (CGRect){0,64,[UIScreen mainScreen].bounds.size.width,[UIScreen mainScreen].bounds.size.height - 64};
    //被模态出来控制器的view尺寸

    CGFloat width = 200;
    CGFloat height = 300;
    CGFloat presentedViewX = ([UIScreen mainScreen].bounds.size.width - width) *0.5;
    CGFloat presentedViewY = 0;
    self.presentedView.frame = CGRectMake(presentedViewX,presentedViewY, width, height);

    //添加蒙板在presentedView下面
    [self.containerView insertSubview:self.coverView belowSubview:self.presentedView];

}

//蒙板点击方法
- (void)coverTouch
{
    [UIView animateWithDuration:0.1 animations:^{
        self.coverView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.001];
        [self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
    } completion:^(BOOL finished) {
        [self.coverView removeFromSuperview];
    }];
}

还有很多有意思的动画 , 都可以实现 .当然也可以自行封装一下 ,以供今后使用 , 比如将返回self处改为 继承与NSObject类的对象 , 然后将所有代理方法封装与 该类中

简单效果如下 , 在showViewController中可以添加控件 , 比如常见的下拉tableView , collectionView , 九宫格按钮等等 .. .
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值