Ios 显示具有模糊效果的视图控制器
我正在演示一个带有模糊背景效果的视图控制器。iOS 10/XCode 8导致我的动画出现问题。这是演示代码:Ios 显示具有模糊效果的视图控制器,ios,iphone,swift,xcode8,uiblureffect,Ios,Iphone,Swift,Xcode8,Uiblureffect,我正在演示一个带有模糊背景效果的视图控制器。iOS 10/XCode 8导致我的动画出现问题。这是演示代码: let modalVC = ModalViewController(nibName: "ModalViewController", bundle: nil) modalVC.modalTransitionStyle = .CrossDissolve modalVC.modalPresentationStyle = .OverFullScreen presentViewController
let modalVC = ModalViewController(nibName: "ModalViewController", bundle: nil)
modalVC.modalTransitionStyle = .CrossDissolve
modalVC.modalPresentationStyle = .OverFullScreen
presentViewController(modalVC, animated: true, completion: nil)
在ModalViewController中的viewDidLoad()
函数上添加模糊:
let blurEffect = UIBlurEffect(style: .Light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
view.addSubview(blurEffectView)
view.sendSubviewToBack(blurEffectView)
ModalViewController
有一个清晰的背景,我添加了一个带有暗模糊效果的BlurEffectView
。以编程方式尝试了前面的代码段和Interface Builder
在iOS 8和iOS 9上,.crosssolve
转换处理了“褪色”,但在iOS 10(设备和模拟器)上测试后,视图显示为深色半透明背景色,而不是模糊
.crosssolve
动画完成后,背景颜色将更改为实际的模糊效果背景。知道为什么会这样吗
还尝试在模式视图控制器的
viewDidLoad()
的开头和结尾添加layoutifneed()
。我使用的是swift 2.3,首先,我将此解决方案视为临时解决方案,因为我必须假设此新引入的行为是一个bug,将在将来的更新中修复。这会使模糊效果在动画期间而不是之后突然出现时,变得不那么明显。仍然没有iOS 9和向后版本那么好,但是稍微好一点
presentViewController(modalVC, animated: false, completion: nil)
override func viewDidLoad() {
super.viewDidLoad()
view.alpha = 0
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
UIView.animateWithDuration(0.25) {
self.view.alpha = 1
}
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
UIView.animateWithDuration(0.25) {
self.view.alpha = 0
}
}
唯一正确的方法是创建自定义模态转换和动画效果属性。见嗨, 您需要创建一个新的
UIViewControllerAnimatedTransitioning
然后在animateTransition(使用transitionContext:UIViewControllerContextTransitioning)
中,您需要对动画进行编码
现在在iOS 10中,您可以使用UIViewPropertyAnimator
来设置UIVisualBlurEffect
的BlurRadius
动画
结果:
这里有一个用法示例:
弗斯特
您需要创建模糊过渡
class BlurModalPresentation: NSObject,UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval{
return 0.5
}
//This is the blur view used for transition
var blurView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.light))
var destinationView : UIView!
var animator: UIViewPropertyAnimator?
// This method can only be a nop if the transition is interactive and not a percentDriven interactive transition.
func animateTransition(using transitionContext: UIViewControllerContextTransitioning){
let containerView = transitionContext.containerView
_ = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
let toVc = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
destinationView = toVc!.view
destinationView.alpha = 0.0
//Here we add the blur view and set it effect to nil
blurView.effect = nil
blurView.frame = containerView.bounds
self.blurTransition(transitionContext) {
self.unBlur(transitionContext, completion: {
self.blurView.removeFromSuperview()
transitionContext.completeTransition(true)
})
}
containerView.addSubview(toVc!.view)
containerView.addSubview(blurView)
}
//This methods add the blur to our view and our destinationView
func blurTransition(_ context : UIViewControllerContextTransitioning,completion: @escaping () -> Void){
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: self.transitionDuration(using: context)/2, delay: 0, options: UIViewAnimationOptions.curveLinear, animations: {
self.destinationView.alpha = 0.5
self.blurView.effect = UIBlurEffect(style: UIBlurEffectStyle.light)
}, completion: { (position) in
completion()
})
}
//This Method remove the blur view with an animation
func unBlur(_ context : UIViewControllerContextTransitioning,completion: @escaping () -> Void){
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: self.transitionDuration(using: context) / 2, delay:0, options: UIViewAnimationOptions.curveLinear, animations: {
self.destinationView.alpha = 1.0
self.blurView.effect = nil
}, completion: { (position) in
completion()
})
}
}
然后
您需要在ViewController
中设置转换委托:
import UIKit
class ViewController: UIViewController,UIViewControllerTransitioningDelegate {
let blurModalPresentation = BlurModalPresentation()
override func viewDidLoad() {
super.viewDidLoad()
}
func showVC(){
let str = self.storyboard!
let vc = str.instantiateViewController(withIdentifier: "YourViewControllerIdentifier")
vc.transitioningDelegate = self
self.present(vc, animated: true, completion: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?{
return blurModalPresentation
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?{
return blurModalPresentation
}
}
我也发现了这种令人讨厌的行为变化。您是否尝试过关闭过渡样式并手动处理动画?尝试过后,效果会更好,但模糊仍有轻微延迟。只是不那么引人注目,有一个可访问性功能,它可以禁用模糊,供忘记这一点的人使用。同样+1表示OP,我也有同样的问题。我有一个表格视图,在显示的VC后面有自定义单元格。模糊只适用于交叉溶解动画结束时后面的东西,然后突然模糊了呈现的VC。是的,这似乎是目前唯一的解决办法,但额外的延迟有点烦人。在接受之前,我会把这个问题留一段时间,希望有人能想出一个替代的解决方案。我理解你的观点,但你可能想将步骤1编辑为
presentViewController(modalVC,动画:false,完成:nil)
Oops,谢谢@Fdo!将动画
更改为假
。我不希望把这个答案选作解决方案,因为它远非完美无缺。也希望有人能想出更好的办法!