iOS-自定义转场动画

前言

说到APP的转场动画,大家一定会想到push和pop来实现转场动画,这是苹果用了很多年提供的自带的方法,而且我相信大家在APP开发的时候,很多小伙伴都会选择自带的转场动画,很少去自定义,不论你是大神还是小白菜,本小白菜也是一样,毕竟作为程序员的我们已经很累了,项目经理不提我们也很少回去做,但是我们工作不是为了工作而工作,是为了丰富充实自己。

自定义UINavigationController

当UINavigationController对UIViewController进行pop或者push的时候,我们需要让UIViewController知道我们进行这些操作,这里我们需要UINavigationController的代理UINavigationControllerDelegate,UINavigationControllerDelegate的代理方法有六种,这里我们只需要一张,那就是:

#pragma mark - UINavigationControllerDelegate
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC;

代码如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.delegate = self;
}

#pragma mark - UINavigationControllerDelegate
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
    ZFJ_Animation *ZFJAnimation = [[ZFJ_Animation alloc]init];
    ZFJAnimation.operation = operation;
    ZFJAnimation.animationType = _animationType;
    return (id)ZFJAnimation;
}

自定义动画(ZFJ_Animation)

ZFJ_Animation这个类继承于NSObject,参数如下:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, ZFJ_AnimationType) {
    ZFJ_AnimationType1,
    ZFJ_AnimationType2,
    ZFJ_AnimationType3
};

@interface ZFJ_Animation : NSObject

@property (nonatomic,assign) UINavigationControllerOperation operation;

@property (nonatomic,assign) ZFJ_AnimationType animationType;//动画类型

@end

参数说明
operation用来接收控制器的转场类型,UINavigationControllerOperation是个枚举类型,类型如下:

typedef NS_ENUM(NSInteger, UINavigationControllerOperation) {
    UINavigationControllerOperationNone,
    UINavigationControllerOperationPush,
    UINavigationControllerOperationPop,
};

看到这个枚举大家就明白了,看你的UIViewController是push还是pop,这样我们可以根据这个类型来定义不同的类型;animationType我自定义转场的动画类型,也是一个枚举,因为在ZFJ_Animation里面我打算定义几个不同的动画类型;当然最重要的就是这个动画控制器的类必须遵循一个代理方法UIViewControllerAnimatedTransitioning,代理的里面的两个方法也必须要实现,代理方法如下:

@protocol UIViewControllerAnimatedTransitioning <NSObject>

// This is used for percent driven interactive transitions, as well as for
// container controllers that have companion animations that might need to
// synchronize with the main animation.
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
// This method can only  be a nop if the transition is interactive and not a percentDriven interactive transition.
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;

@optional

代理说明

a.transitionDuration:这个方法返回自定义动画的执行时间;

b.animateTransition:这个方法是我们这个动画管理类的核心,我们需要自定义什么样的动画全部在这里面执行;

上代码:

#pragma mark - UIViewControllerAnimatedTransitioning
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{
    return 0.4;
}

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    UIView *containerView = transitionContext.containerView;

    if(self.animationType == ZFJ_AnimationType1){
        //动画一
        [containerView addSubview:toViewController.view];
        
        CGRect fromViewStartFrame = [transitionContext initialFrameForViewController:fromViewController];
        CGRect toViewEndFrame = [transitionContext finalFrameForViewController:toViewController];
        CGRect fromViewEndFrame = fromViewStartFrame;
        CGRect toViewStartFrame = toViewEndFrame;
        
        if(self.operation == UINavigationControllerOperationPush){
            //PUSH
            toViewStartFrame.origin.y -= toViewEndFrame.size.height;
        }else if (self.operation == UINavigationControllerOperationPop){
            //POP
            fromViewEndFrame.origin.y -= fromViewStartFrame.size.height;
            [containerView sendSubviewToBack:toViewController.view];
        }
        //这里面 你可以自定义动画
        fromViewController.view.frame = fromViewStartFrame;
        toViewController.view.frame = toViewStartFrame;
        
        //动画
        CGFloat duration = [self transitionDuration:transitionContext];
        [UIView animateWithDuration:duration animations:^{
            fromViewController.view.frame = fromViewEndFrame;
            toViewController.view.frame = toViewEndFrame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }else if(self.animationType == ZFJ_AnimationType2){
        //动画二
    }else if (self.animationType == ZFJ_AnimationType3){
        //动画三
    }
    
}

说明:这里面我定义了三种动画,因为页面展示太长,我就展示一种动画。

UIViewController调用

- (void)nextBtnClick:(UIButton *)nextBtn{
    NSInteger index = nextBtn.tag - 100;
    ZFJ_NavViewController *nvc = (ZFJ_NavViewController *)self.navigationController;
    nvc.animationType = (ZFJ_AnimationType)index;
    ZFJ_NextViewController *zvc = [[ZFJ_NextViewController alloc]init];
    [nvc pushViewController:zvc animated:YES];
}

效果展示

DEMO下载

点击下载

http://download.csdn.net/detail/u014220518/9883291

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值