我编写了一个自定义 segue 来获得淡入淡出效果,我试图通过在source view controller
下方插入destination view controller
并将source view controller
的alpha
动画化为零来实现。
但是,在源下方添加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
})
})
}
}
}