如果我提供destinationViewController,自定义淡入淡出不会动画

时间:2016-05-31 14:39:20

标签: ios swift animation segue

我已经编写了一个自定义区域来获得淡入淡出效果,我试图通过在destination view controller下面插入source view controller并为alpha设置动画来实现这一效果source view controller为零。

但是,在源下面添加destination view controller似乎会取消动画,而segue的表现就好像是一个禁用动画的常规present

import UIKit

class FadeSegue: UIStoryboardSegue {

    override func perform() {
        // Get the view of the source
        let sourceViewControllerView = self.sourceViewController.view
        // Get the view of the destination
        let destinationViewControllerView = self.destinationViewController.view

        let screenWidth = UIScreen.mainScreen().bounds.size.width
        let screenHeight = UIScreen.mainScreen().bounds.size.height

        // Make the destination view the size of the screen
        destinationViewControllerView.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)

        if let window = UIApplication.sharedApplication().keyWindow {
            // Insert destination below the source
            // Without this line the animation works but the transition is not smooth as it jumps from white to the new view controller
            window.insertSubview(destinationViewControllerView, belowSubview: sourceViewControllerView)

            // Animate the fade, remove the destination view on completion and present the full view controller
            UIView.animateWithDuration(0.4, animations: {
                sourceViewControllerView.alpha = 0.0
                }, completion: { (finished) in
                    destinationViewControllerView.removeFromSuperview()
                    self.sourceViewController.presentViewController(self.destinationViewController, animated: false, completion: nil)
            })
        }
    }
}

3 个答案:

答案 0 :(得分:4)

你好我认为你需要的是这个

override func perform() {
        // Get the view of the source
        let sourceViewControllerView = self.sourceViewController.view
        // Get the view of the destination
        let destinationViewControllerView = self.destinationViewController.view

        let screenWidth = UIScreen.mainScreen().bounds.size.width
        let screenHeight = UIScreen.mainScreen().bounds.size.height

        // Make the destination view the size of the screen
        destinationViewControllerView.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)

            // Insert destination below the source
            // Without this line the animation works but the transition is not smooth as it jumps from white to the new view controller
            destinationViewControllerView.alpha = 0;
            sourceViewControllerView.addSubview(destinationViewControllerView);
            // Animate the fade, remove the destination view on completion and present the full view controller
            UIView.animateWithDuration(10, animations: {
                destinationViewControllerView.alpha = 1;
                }, completion: { (finished) in
                    destinationViewControllerView.removeFromSuperview()
                    self.sourceViewController.presentViewController(self.destinationViewController, animated: false, completion: nil)
            })
        }
    }

我希望这能帮到你

答案 1 :(得分:2)

基于@ reinier-melian

的答案,略微修改了Swift 4.1兼容解决方案
/// Performs a simple fade between source and destination view controller.
class Fade: UIStoryboardSegue {

    override func perform() {

        guard let destinationView = self.destination.view else {
            // Fallback to no fading
            self.source.present(self.destination, animated: false, completion: nil)
            return
        }

        destinationView.alpha = 0
        self.source.view?.addSubview(destinationView)

        UIView.animate(withDuration: CATransaction.animationDuration(), animations: {
            destinationView.alpha = 1
        }, completion: { _ in
            self.source.present(self.destination, animated: false, completion: nil)
        })
    }
}

答案 2 :(得分:1)

这就是我最终为了我的目的所做的事情。一旦屏幕上的所有内容都已动画显示并在占位符中淡入淡出,它会将placeholder view的基本ui元素放在顶部,然后显示destination view controller并删除placeholderdestination view controller然后在其所有元素中设置动画,实质上使转换不可见,看起来像一个动画:

import UIKit

class FadeSegue: UIStoryboardSegue {

    var placeholderView: UIViewController?

    override func perform() {
        let screenWidth = UIScreen.mainScreen().bounds.size.width
        let screenHeight = UIScreen.mainScreen().bounds.size.height

        if let placeholder = placeholderView {
            placeholder.view.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)

            placeholder.view.alpha = 0
            sourceViewController.view.addSubview(placeholder.view)

            UIView.animateWithDuration(0.4, animations: {
                placeholder.view.alpha = 1
                }, completion: { (finished) in
                    self.sourceViewController.presentViewController(self.destinationViewController, animated: false, completion: {
                        placeholder.view.removeFromSuperview()
                    })
            })
        } else {
            self.destinationViewController.view.alpha = 0.0

            self.sourceViewController.presentViewController(self.destinationViewController, animated: false, completion: {
                UIView.animateWithDuration(0.4, animations: {
                    self.destinationViewController.view.alpha = 1.0
                })
            })
        }
    }
}

和放松:

import UIKit

class FadeSegueUnwind: UIStoryboardSegue {

    var placeholderView: UIViewController?

    override func perform() {
        let screenWidth = UIScreen.mainScreen().bounds.size.width
        let screenHeight = UIScreen.mainScreen().bounds.size.height

        if let placeholder = placeholderView {
            placeholder.view.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)

            placeholder.view.alpha = 0
            sourceViewController.view.addSubview(placeholder.view)
            UIView.animateWithDuration(0.4, animations: {
                placeholder.view.alpha = 1
                }, completion: { (finished) in
                    self.sourceViewController.dismissViewControllerAnimated(false, completion: nil)
            })
        } else {
            self.destinationViewController.view.alpha = 0.0

            self.sourceViewController.dismissViewControllerAnimated(false, completion: { 
                UIView.animateWithDuration(0.4, animations: { 
                    self.destinationViewController.view.alpha = 0.0
                })
            })
        }
    }
}