自定义淡入淡出 Segue 不动画,如果我呈现目的地视图控制器



我编写了一个自定义 segue 来获得淡入淡出效果,我试图通过在source view controller下方插入destination view controller并将source view controlleralpha动画化为零来实现。

但是,在源下方添加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)
            })
        }
    }
}

你好,我想你需要的是这个

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)
            })
        }
    }

我希望这对你有所帮助

基于

@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)
        })
    }
}

这就是我最终为我的目的所做的。一旦屏幕上的所有内容都已动画化并在占位符中淡出,它将带有基本 UI 元素的placeholder view放在顶部,然后显示destination view controller并删除placeholder。然后,destination 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
                })
            })
        }
    }
}

最新更新