【问题标题】:Custom segue transition animation自定义 segue 过渡动画
【发布时间】:2017-07-29 03:11:40
【问题描述】:

我正在开发一个使用导航控制器的应用程序。我有一个特定的视图控制器,在导航栏中有一个左右按钮,每个按钮都连接到不同的视图控制器。当我按下右键时,我只调用self.performSegue(withIdentifier: "ToDestination", sender: nil),当我弹回来时,我调用_ = self.navigationController?.popViewController(animated: true)

我的问题是当我按下左键时。我可以按下和弹出,但我希望过渡与右侧按钮相反。由于我按下左键,我希望 segue 从左到右转换,当我弹出时,我希望 segue 从右到左转换。

我可以通过以下方式让转换按照我想要的方式工作:

//push
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SearchController") as! SearchController
let transition: CATransition = CATransition()
let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.duration = 0.5
transition.timingFunction = timeFunc
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
self.navigationController!.view.layer.add(transition, forKey: kCATransition)
self.navigationController!.pushViewController(vc, animated: true)

//pop
let transition: CATransition = CATransition()
let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.duration = 0.5
transition.timingFunction = timeFunc
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
self.navigationController!.view.layer.add(transition, forKey: kCATransition)
_ = self.navigationController?.popViewController(animated: true)

这可行,但是在视图控制器之间转换时会出现黑色闪烁。有没有更好的方法来获取默认的过渡动画?

【问题讨论】:

    标签: swift catransition


    【解决方案1】:

    实现这一点的最佳方法是通过遵循UIViewControllerAnimatedTransitioning 协议来创建自定义推送和弹出动画:-

    //CustomPushAnimation class
    
    import UIKit
    
    class CustomPushAnimation: NSObject, UIViewControllerAnimatedTransitioning {
    
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.2
        }
    
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            let containerVw = transitionContext.containerView
            let fromViewController = transitionContext.viewController(forKey: .from)
            let toViewController = transitionContext.viewController(forKey: .to)
            guard let fromVc = fromViewController, let toVc = toViewController else { return }
            let finalFrame = transitionContext.finalFrame(for: toVc)
            //Below line will start from left
            toVc.view.frame = finalFrame.offsetBy(dx: -finalFrame.size.width/2, dy: 0)
            containerVw.addSubview(toVc.view)
            UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                toVc.view.frame = finalFrame
                fromVc.view.alpha = 0.5
            }, completion: {(finished) in
                transitionContext.completeTransition(finished)
                fromVc.view.alpha = 1.0
            })
        }
    }
    
    
    
    //CustomPopAnimation class
    import UIKit
    
    class CustomPopAnimation: NSObject, UIViewControllerAnimatedTransitioning {
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.2
        }
    
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            let containerView = transitionContext.containerView
            let fromViewController = transitionContext.viewController(forKey: .from)
            let toViewController = transitionContext.viewController(forKey: .to)
            guard let fromVc = fromViewController,
                let toVc = toViewController,
                let snapshotView = fromVc.view.snapshotView(afterScreenUpdates: false)
                else { return }
            let finalFrame = transitionContext.finalFrame(for: fromVc)
            toVc.view.frame = finalFrame
            containerView.addSubview(toVc.view)
            containerView.sendSubview(toBack: toVc.view)
            snapshotView.frame = fromVc.view.frame
            containerView.addSubview(snapshotView)
            fromVc.view.removeFromSuperview()
            UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                //Below line will start from right
                snapshotView.frame = finalFrame.offsetBy(dx: -finalFrame.size.width, dy: 0)
            }, completion: {(finished) in
                snapshotView.removeFromSuperview()
                transitionContext.completeTransition(finished)
            })
        }
    }
    

    最后你需要向新的 View 控制器展示设置 动画标志为真,否则将无法正常工作

    //Below code should be inside YourViewController
        let vc = UIStoryboard(name: "storyboardName", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerIdentifier")            let navigationController = BaseNavigationController(rootViewController: vc)
        navigationController.transitioningDelegate = self
        present(navigationController, animated: true, completion: nil)
    

    你还需要符合 UIViewControllerTransitioningDelegate 协议以工作动画

      extension YourViewController: UIViewControllerTransitioningDelegate {
        func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
                return customPushAnimation
            }
    
        func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
                return customPopAnimation
            }
        }
    

    【讨论】:

    • 嘿伙计,我想更改您的代码,我想更改为从右到左,因为您的代码是从左到右的...我想知道我需要更改哪个部分才能实现?
    猜你喜欢
    • 2013-11-23
    • 1970-01-01
    • 2014-03-04
    • 2012-06-01
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多