美文网首页
瞎搞iOS转场(-)

瞎搞iOS转场(-)

作者: 谢微一直都得踢足球 | 来源:发表于2016-09-08 11:53 被阅读112次

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

    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<UIViewControllerContextTransitioning>)transitionContext ;
    
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext;
    
    

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

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

    最后贴出我动画的逻辑

    - (void)ThrerDPushAnimation:(id<UIViewControllerContextTransitioning>)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<UIViewControllerAnimatedTransitioning>)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 <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                                       interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController NS_AVAILABLE_IOS(7_0){
        // 这里要判断 是pop返回 还是手势返回
        return self.manager.isInteractive?self.manager:nil;
    }
    

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

    相关文章

      网友评论

          本文标题:瞎搞iOS转场(-)

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