瞎搞iOS转场(-)

想写很久了 一直没时间 刚好项目做完了 现在来写篇吧 有很多不足之处希望大家多多指正批评 好 下面进入正题
先上效果图

瞎搞iOS转场(-)_第1张图片
pushTransition.gif

这其实一个自定义push转场动画 关于转场动画 网上资料也很多 我现在贴出一篇我觉得写的很好的 传送门

分析动画

先要了解几个概念 from 和 to 在代码中经常看到fromView和toView这类的
1.fromView表示当前视图
2.toView表示要跳转到的视图
我们似乎可以看到是fromView旋转了180° 其实不是这样的 我是这样处理的 先让toView旋转90° 然后此时fromView和头view形成了一个+形状 然后让fromView旋转90° 完成后 toView在旋转90° 这样就达到这个动画 当然要注意旋转的方向 这些在代码中有详细的注释

定义转场动画

首先定义一个遵循了UIViewControllerAnimatedTransitioning协议的类。并且实现下面2个方法

- (NSTimeInterval)transitionDuration:(id)transitionContext ;

- (void)animateTransition:(id)transitionContext;

第一个方法是返回转场的时间 第二个方法可以拿到转场的上下文(上下文大家很明白吧)这个上下文里面就包含我们转场需要的几乎所有元素 包括fromView fromVC toView 等等 然后我们这里写我们的动画的逻辑就可以了
需要注意的一点就是 我们要把push 和 pop的动画分开 所以我是这样处理的

- (void)animateTransition:(id)transitionContext{
    switch (self.type) {
        case XWPushTransitionManagerPush:
            [self doPushAnimation:transitionContext];
            break;
        case XWPushTransitionManagerPop:
            [self doPopAnimation:transitionContext];
            break;
        default:
            break;
    }
}

最后贴出我动画的逻辑

- (void)ThrerDPushAnimation:(id)transitionContext{
    
    // 将要转场出来的view
    UIView *toView =[transitionContext viewForKey:UITransitionContextToViewKey];
    // 当前的view
    UIView *formView = [transitionContext viewForKey:UITransitionContextFromViewKey];
    // 转场的容器
    UIView *contaniView = [transitionContext containerView];
    contaniView.backgroundColor = [UIColor orangeColor];
    CATransform3D percatier = CATransform3DIdentity;
    // 设置m34 才有立体效果
    percatier.m34 = -1.0/500;
    //sublayerTranform
    // 设置了父视图的sublayerTranform 子视图就都有这个transform
    contaniView.layer.sublayerTransform = percatier;
    [contaniView  addSubview:toView];
    [contaniView  addSubview:formView];
    
    //toview 默认旋转90
    CATransform3D tranform1 = CATransform3DMakeRotation(-M_PI_2,0,1,0);
    toView.layer.transform = tranform1;
    
    
    // formview 的旋转角度 也是90  当formview旋转到90度时候 移除formview  并且toview开始动画
    // 其实2个view 各自只旋转了90度
    CATransform3D tranform2 = CATransform3DMakeRotation(M_PI_2,0,1,0);
    
    // 关键帧动画
    // StartTime:动画开始时间         取值0-1 指的是比例
    // relativeDuration: 动画持续时间 取值0-1 指的是比例
    [UIView animateKeyframesWithDuration:Time delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
        [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.5 animations:^{
            // 当前的view 旋转90度
            formView.layer.transform = tranform2;
        }];
        
        // formview 动画完成后 toView 进行动画
        [UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{
            toView.layer.transform = CATransform3DIdentity;
        }];
    } completion:^(BOOL finished) {
         // 动画完成之后 要告诉系统 转场完成了 不然会出现bug
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        [formView removeFromSuperview];
    }];
}

最后我们设置转场的代理并且设置UINavigationControllerDelegate 在代理方法中返回我们定义的类

#pragma mark -- 代理
- (id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
    //分pop和push两种情况分别返回动画过渡代理相应不同的动画操作
    return [XWPushTransitionManager transitionWithType:operation == UINavigationControllerOperationPush ? XWPushTransitionManagerPush : XWPushTransitionManagerPop];
}

这里的UINavigationControllerOperation 这个枚举就是来区分是push 还是 pop 我们只需要返回对应的就可以拉
至此 我们的瞎搞push转场就完成了 当然你还得实现pop 这很简单 就动画的反向

手势驱动

最后我们在加上一个效果 就是手势驱动 啥事手势驱动呢 系统默认的 Push 和 Pop 动画都支持手势驱动 并且可以根据手势移动距离改变动画完成度 在iOS7以后 苹果为我们提供了一个UIPercentDrivenInteractiveTransition这个类 这个类就是专门来做手势驱动的 废话不多说 下面直接开搞
1.自定义一个类 继承于UIPercentDrivenInteractiveTransition 重写初始化方法 传入一个控制器(一般是push出来的vc)
2.个该vc添加一个Pan手势
3.在手势的监听方法里面计算手势移动的百分比 并使用 UIPercentDrivenInteractiveTransition 属性的 updateInteractiveTransition 方法实时更新百分比
4.最后实现UINavigationControllerDelegate的一个代理方法

- (nullable id )navigationController:(UINavigationController *)navigationController
                                   interactionControllerForAnimationController:(id ) animationController NS_AVAILABLE_IOS(7_0){
    // 这里要判断 是pop返回 还是手势返回
    return self.manager.isInteractive?self.manager:nil;
}

至此 手势驱动也完成了啊 是不是很简单呢 其实不是 这里面水很深的 有很多细节 尤其加入了手势驱动 pop动画尤其得注意了 具体的我在代码里面注释了 贴出demo地址demo地址
最后希望大家pi'p

你可能感兴趣的:(瞎搞iOS转场(-))