How to Fade a Uivisualeffectview And/Or Uiblureffect in and Out

How to fade a UIVisualEffectView and/or UIBlurEffect in and out?

I think this is new in iOS9, but you can now set the effect of a UIVisualEffectView inside an animation block:

let overlay = UIVisualEffectView()
// Put it somewhere, give it a frame...
UIView.animate(withDuration: 0.5) {
overlay.effect = UIBlurEffect(style: .light)
}

Set it to nil to remove.

VERY IMPORTANT - When testing this on the simulator, make sure to set your simulator's Graphics Quality Override to High Quality in order for this to work.

How can blurriness of UIVisualEffectView be modified while dragging in iOS?

There is a way :)

As you've noticed, you can animate from a nil effect to an effect like UIBlurEffectStyleDark so if we add an animation and then pause the layer's animations we can control the progress of the effect by adjusting the layer's timeOffset!

- (void) setupBlur {
// Setup the blur to start with no effect
self.blurredEffectView = [[UIVisualEffectView alloc] initWithEffect:nil];

// Add animation to desired blur effect
[UIView animateWithDuration:1.0 animations:^{
[self.blurredEffectView setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
}];

// Pause layer animations
self.blurredEffectView.layer.speed = 0;
}

Adjust blur between 0.0 and 1.0 (animation duration):

- (void) adjustBlur:(CGFloat)blurIntensity {
self.blurredEffectView.layer.timeOffset = blurIntensity;
}
  • Note: this won't work on iOS 8 where UIBlurEffect animations aren't supported.

Less Blur with `Visual Effect View with Blur`?

The reason you're getting heavy blur is that the blur effect style affects the brightness level of the image, not the amount of blur applied.

enter image description here

Unfortunately, although Apple clearly has the ability to control the amount of blur applied programmatically--try dragging down slowly on the launchpad to watch the Spotlight blurring transition--I don't see any public API to pass a blur amount to UIBlurEffect.

This post claims that adjusting the background color alpha will drive the blur amount. It's worth a try, but I don't see where that is documented: How to fade a UIVisualEffectView and/or UIBlurEffect in and out?

Draw hole on UIBlurEffect

In iOS 10 you have to use mask property of UIVisualEffectView instead of CALayer's mask.

I saw this covered in the release notes for some early betas of iOS 10 or Xcode 8, but I can not find those notes now :). I'll update my answer with a proper link as soon as I find it.

So here is the code that works in iOS 10/Xcode 8:

class ViewController: UIViewController {
@IBOutlet var blurView: UIVisualEffectView!

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

updateBlurViewHole()
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

updateBlurViewHole()
}

func updateBlurViewHole() {
let maskView = UIView(frame: blurView.bounds)
maskView.clipsToBounds = true;
maskView.backgroundColor = UIColor.clear

let outerbezierPath = UIBezierPath.init(roundedRect: blurView.bounds, cornerRadius: 0)
let rect = CGRect(x: 150, y: 150, width: 100, height: 100)
let innerCirclepath = UIBezierPath.init(roundedRect:rect, cornerRadius:rect.height * 0.5)
outerbezierPath.append(innerCirclepath)
outerbezierPath.usesEvenOddFillRule = true

let fillLayer = CAShapeLayer()
fillLayer.fillRule = kCAFillRuleEvenOdd
fillLayer.fillColor = UIColor.green.cgColor // any opaque color would work
fillLayer.path = outerbezierPath.cgPath
maskView.layer.addSublayer(fillLayer)

blurView.mask = maskView;
}
}

Swift 2.3 version:

class ViewController: UIViewController {
@IBOutlet var blurView: UIVisualEffectView!

override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)

updateBlurViewHole()
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

updateBlurViewHole()
}

func updateBlurViewHole() {
let maskView = UIView(frame: blurView.bounds)
maskView.clipsToBounds = true;
maskView.backgroundColor = UIColor.clearColor()

let outerbezierPath = UIBezierPath.init(roundedRect: blurView.bounds, cornerRadius: 0)
let rect = CGRect(x: 150, y: 150, width: 100, height: 100)
let innerCirclepath = UIBezierPath.init(roundedRect:rect, cornerRadius:rect.height * 0.5)
outerbezierPath.appendPath(innerCirclepath)
outerbezierPath.usesEvenOddFillRule = true

let fillLayer = CAShapeLayer()
fillLayer.fillRule = kCAFillRuleEvenOdd
fillLayer.fillColor = UIColor.greenColor().CGColor
fillLayer.path = outerbezierPath.CGPath
maskView.layer.addSublayer(fillLayer)

blurView.maskView = maskView
}
}

UPDATE

Well, it was Apple Developer forums discussion and not iOS release notes. But there are answers from Apple's representatives so I think, this information may be considered "official".

A link to the discussion: https://forums.developer.apple.com/thread/50854#157782

Masking the layer of a visual effect view is not guaranteed to produce
the correct results – in some cases on iOS 9 it would produce an
effect that looked correct, but potentially sourced the wrong content.
Visual effect view will no longer source the incorrect content, but
the only supported way to mask the view is to either use cornerRadius
directly on the visual effect view’s layer (which should produce the
same result as you are attempting here) or to use the visual effect
view’s maskView property.

enter image description here



Related Topics



Leave a reply



Submit