美文网首页
基于Swift3.0下的转场动画

基于Swift3.0下的转场动画

作者: 哎呀不错 | 来源:发表于2016-09-20 09:25 被阅读0次

我们知道,当一个控制器要弹出另一个控制器时,主要分为两大类,第一种是带导航栏的,push/show等等。这里不作解释,本文章主要针对modal方式自定义转场动画,效果如下:


transitionAnimation.gif

实现这样的效果其实并不复杂,但是有很多细节需要注意。
首先,当我们不自定义转成动画的时候一般都说是像下面这么写就够了。

self.present(crossDissolveSecondVC, animated: true, completion: nil)

从上面的代码中我们似乎找不到自定义动画的接口,那么这里就需要了解一个关键了---转场动画代理 UIViewControllerTransitioningDelegate
如下:

// 设置被modal出来的控制器的样式,此处不写这句代码也可。
 crossDissolveSecondVC.modalPresentationStyle = .fullScreen
// crossDissolveSecondVC表示被modal出来的控制器。
 crossDissolveSecondVC.transitioningDelegate = self

设置完这句以后,我们遵循协议,进入看一下这个协议中的关键方法:

    // present动画
    @objc(animationControllerForPresentedController:presentingController:sourceController:) func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return DHPresentAnimator()
    }
    // dismiss动画
    @objc(animationControllerForDismissedController:) func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {  
//        return DHPresentAnimator()
        return DHDismissAnimator()
    }

我们可以发现上述两个代理方法,一个是针对present的代理方法,
一个是针对dismiss的时候的代理方法。这两个方法的共同点是都需要返回一个遵守UIViewControllerAnimatedTransitioning协议的对象。
那么下一步我们来创建这样一个遵守协议的类。
如下:

class DHPresentAnimator: NSObject, UIViewControllerAnimatedTransitioning, CAAnimationDelegate {
}

当你写到这里的时候会报错,因为遵守UIViewControllerAnimatedTransitioning协议的类必须实现两个代理方法,这里只需要按照提示实现即可。具体我们看这两个方法各有什么作用。

// MARK: - CAAnimationDelegate的代理方法
extension DHPresentAnimator {
    
    // 这个代理方法设置动画的执行时间
    @objc(transitionDuration:) public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        
        return transitionDuration
    }
    // 这个方法里面主要实现动画细节
    @objc(animateTransition:) public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        
        // 记录transitionContext
        transitionCtx = transitionContext
        
        // 这里指的是firstVC
//        let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
        
        // 这里指的是secondVC
        toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
        
        let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)
        
        toView = transitionContext.view(forKey: UITransitionContextViewKey.to)
        
        let containerView = transitionContext.containerView
        
        print(fromView.self)
        print(toView.self)
        print(containerView.self)
        // 这一步是必须的,当prsent动画时需要将modal出来的视图加到containerView中去,
        containerView.addSubview(toView!)
        
        // 加入旋转动画。
        toView?.layer.add(rotateAnimation, forKey: "rotate")
        
    }

}

以上代码我创建的是一个旋转的动画(CAAnimation),如下:

    // 动画的执行时间
    let transitionDuration = 2.0
    
    // 旋转动画
    lazy var rotateAnimation: CABasicAnimation = {
        let animation = CABasicAnimation(keyPath: "transform.rotation")
        animation.fromValue = 0.0
        animation.toValue = M_PI * 2
        animation.duration = self.transitionDuration
        animation.delegate = self

        return animation
    }()
    

这里最关键的一部就是,当动画执行完毕以后我们需要执行以下代码:

// 这段代码的意思相当于动画的结束标志。
 transitionCtx?.completeTransition(!(transitionCtx?.transitionWasCancelled)!)

那么问题来了?我们怎么知道动画什么时候执行完毕,这个时候还是得找代理CAAnimationDelegate,刚刚我们在懒加载中定义动画的一些旋转参数时就已经设置了代理,然后遵循CAAnimationDelegate这个代理协议。我们不难找到:

// MARK: - CAAnimationDelegate 的代理方法
extension DHPresentAnimator {
    
    public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        print("animationEnd")
       
        // 动画结束以后会调该方法
        if flag == true { // 代表正常结束
            transitionCtx?.completeTransition(!(transitionCtx?.transitionWasCancelled)!)
            print(toView?.frame)
            
            // 移除这个动画
            toView?.layer.removeAnimation(forKey: "rotate")
//            toView?.alpha = 1.0
        }
    
    }
    func animationDidStart(_ anim: CAAnimation) {
        print("animationBegin")
    }
}

说到这里转场动画的基本套路就说完了,其实是怎么一回事呢?要想自定义转场动画,无非就是遵循协议,实现代理方法,在代理方法中拿到即将要出现的视图,拿到这个视图以后我们做相关操作,比如旋转,平移,等等都可以。这就是转场动画的核心部分。
相关代码链接如下:
https://github.com/iLMagic/-.git

相关文章

  • 基于Swift3.0下的转场动画

    我们知道,当一个控制器要弹出另一个控制器时,主要分为两大类,第一种是带导航栏的,push/show等等。这里不作解...

  • CATransition 转场动画

    今天我们来学习一下新的动画类型, 转场动画,什么是转场动画呢?转场动画就是从一个场景以动画的形式过渡到下一个场景,...

  • iOS转场动画

    iOS自定义转场动画 首先介绍下iOS转场动画控制相关API 动画控制器 (Animation Controlle...

  • 聊聊Android的转场动画

    Android的转场动画包括:场景动画,页面的转场动画,页面元素间共享动画。 Android转场动画[https:...

  • iOS-自定义控制器转场动画(present/dismiss)

    一、转场动画类型 iOS控制器转场动画类型可以分为非交互式转场动画和交互式转场动画。 二、转场动画分析 2.1、转...

  • iOS 动画三:transitions 动画

    转场动画 transitions 前两节,我们学习了怎样基于属性(eg. postion 及 alpha)创建动画...

  • iOS - 转场动画

    参考文章:iOS 转场动画一张图看懂 iOS 转场动画iOS自定义转场动画 iOS 转场动画探究(一)

  • iOS开发——登录页面动画、转场动画

    iOS开发——登录页面动画、转场动画 iOS开发——登录页面动画、转场动画

  • 2017笔记——转场动画(一)

    之前就搞过转场动画,可是中途有事耽误了,如今重拾一下,好好梳理一下,搞个Demo出来实践一下。 平移的转场动画: ...

  • 高逼格Android转场动画

    前言 转场动画在交互上非常有优势,本文从转场动画的使用场景和方法起,最后是实现掘金中用户头像的转场动画。 转场动画...

网友评论

      本文标题:基于Swift3.0下的转场动画

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