Blur view controller view

I present the View Controller modally with a background blur effect. IOS 10 / Xcode 8 has a problem with my animation. This is the presentation code:

let modalVC = ModalViewController(nibName: "ModalViewController", bundle: nil) modalVC.modalTransitionStyle = .CrossDissolve modalVC.modalPresentationStyle = .OverFullScreen presentViewController(modalVC, animated: true, completion: nil) 

Adding blur to the viewDidLoad() function in ModalViewController:

 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 has a clean background, and I added a BlurEffectView with a blur effect. I tried programmatically with the previous snippet and in Interface Builder.

In iOS 8 and 9, the .CrossDissolve transition .CrossDissolve care of β€œattenuation,” but after testing on iOS 10 (both on the device and on the simulator), the view appears with a dark translucent background color instead of blurring.

After the .CrossDissolve animation .CrossDissolve , the background color changes to the actual background of the blur effect. Any ideas why this is happening?

Also tried adding layoutIfNeeded() to the beginning and end of viewDidLoad() for the modal controller. I am using swift 2.3

+6
source share
3 answers
Hello,

You need to create a new UIViewControllerAnimatedTransitioning .

Then in animateTransition(using transitionContext: UIViewControllerContextTransitioning) you need to encode the animation.

Now in iOS 10, you can use the UIViewPropertyAnimator to animate the BlurRadius UIVisualBlurEffect .

Result: enter image description here

Here's a usage example: https://github.com/PierrePerrin/PPBlurModalPresentation

First

You need to create a transition blur

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

Then

You need to set up transition delegation in 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 } } 
+4
source

First of all, I see this solution as a temporary workaround because I have to assume that this newly introduced behavior is a bug and will be fixed in future updates. This makes it somewhat less noticeable, since the blur effect appears during the animation, and not later. Still not as good as in iOS 9 and vice versa, but a little better.

  • Current view controller without animation:

     presentViewController(modalVC, animated: false, completion: nil) 
  • Hide your view from the start:

     override func viewDidLoad() { super.viewDidLoad() view.alpha = 0 } 
  • Apply animation manually:

     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 } } 
+1
source

The only right way is to create a special modal transition and an animation effect property. See fooobar.com/questions/177194 / ...

+1
source

All Articles