iOS动画:ViewController过渡动画之UINavigationController转场动画(12)

22 篇文章 0 订阅
21 篇文章 0 订阅

和前一章类似,仅仅是代理方法的不同。
主要用到UINavigationControllerDelegate的代理方法navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController),该代理方法也是需要返回一个UIViewControllerAnimatedTransitioning的可选对象,当返回nil时,UIKit将使用内置系统默认动画,当不为nil时,将使用你自己自定义的动画效果。

现在有这样一个场景
image_1
我们来创建一个动画构造器

class RevealAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    let animationDuration = 2.0
    var operation: UINavigationControllerOperation = .push
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return animationDuration
    }
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        
    }
}

然后在MasterViewController.swift的viewDidLoad中配置代理

	navigationController?.delegate = self

实现代理方法

extension MasterViewController: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        transition.operation = operation
        return transition
    }
}

现在我们来实现动画构造器RevealAnimator中的方法。
因为需要创建一些layer动画,我们先存一下动画上下文。

	weak var storedContext: UIViewControllerContextTransitioning?

然后在animateTransition()中添加初始化转场代码

	storedContext = transitionContext
    if operation == .push {
	    let fromVC = transitionContext.viewController(forKey: .from) as! MasterViewController
        let toVC = transitionContext.viewController(forKey: .to) as! DetailViewController
        
        transitionContext.containerView.addSubview(toVC.view)//将toView添加到容器当中
        toVC.view.frame = transitionContext.finalFrame(for: toVC)//设置toView的坐标
        ...
    }

现在我们添加一个放大logo切换场景的动画

	        let animation = CABasicAnimation(keyPath: "transform")
        animation.fromValue = NSValue(caTransform3D: CATransform3DIdentity)
        animation.toValue = NSValue(caTransform3D: CATransform3DConcat(CATransform3DMakeTranslation(0.0, -10.0, 0.0), CATransform3DMakeScale(150.0, 150.0, 1.0)))
        animation.duration = animationDuration
        animation.delegate = self
        animation.fillMode = kCAFillModeForwards
        animation.isRemovedOnCompletion = false
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
        
        let maskLayer: CAShapeLayer = RWLogoLayer.logoLayer()
        maskLayer.position = fromVC.logo.position
        toVC.view.layer.mask = maskLayer
        maskLayer.add(animation, forKey: nil)
        fromVC.logo.add(animation, forKey: nil)

运行效果
image_2
为了移除fromVC的logo,同样也添加一个动画

	fromVC.logo.add(animation, forKey: nil)

动画结束时,我们需要设置转场动画完成,并移除fromVC的所有动画,再将toVC的mask清空

    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        if let context = storedContext {
            context.completeTransition(!context.transitionWasCancelled)
            let fromVC = context.viewController(forKey: .from) as! MasterViewController
            fromVC.logo.removeAllAnimations()
            let toVC = context.viewController(forKey: .to) as! DetailViewController
            toVC.view.layer.mask = nil
        }
        storedContext = nil
    }

实现效果:
image_2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值