Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fix UIVisualEffectView extra light blur being gray on white background

Apple provides this live blurring view class UIVisualEffectView and you use it with a UIBlurEffect which takes one of three available UIBlurEffectStyles:

enum UIBlurEffectStyle : Int {
    case ExtraLight
    case Light
    case Dark
}

Now for demo purposes I set up two effect views with the styles Light and ExtraLight:

let lightBlur = UIBlurEffect(style: UIBlurEffectStyle.Light)
let extraLightBlur = UIBlurEffect(style: UIBlurEffectStyle.ExtraLight)

let lightView = UIVisualEffectView(effect: lightBlur)
lightView.frame = CGRectMake(10, 30, 150, 150)
self.view.addSubview(lightView)

let extraLightView = UIVisualEffectView(effect: extraLightBlur)
extraLightView.frame = CGRectMake(160, 30, 150, 150)
self.view.addSubview(extraLightView)

So far so good, everything works as expected, they blur images:

image

and kind of work on colors, too:

black red

but when it comes to a white background this happens:

white

The Light effect on the left works as expected, but the ExtraLight effect on the right leaves some kind of gray square behind.

Now the question: Is there any kind of trick or method that would enable me to use an extra light blur effect on white background (with live blurring support) AND remove that ugly gray shadow?

like image 355
Finn Gaida Avatar asked Jul 22 '16 07:07

Finn Gaida


2 Answers

As far as I know the additional tint is a built-in feature of the UIVisualEffectView class. If you examine the view hierarchy with Xcode, you can see that there are two default subviews in the visual effect view instance: UIVisualEffectBackdropView and UIVisualEffectSubview. (I assume that these are private classes.) If you inspect UIVisualEffectSubview you can see that it has a background color which causes the unwanted tint that you've noticed.

I am not sure if there's an officially supported way to remove it, but you can modify this background color by filtering to the name of the private subview:

if let vfxSubView = visualEffectView.subviews.first(where: {
    String(describing: type(of: $0)) == "_UIVisualEffectSubview"
}) {
    vfxSubView.backgroundColor = UIColor.white.withAlphaComponent(0.7)
}

(Swift 5 compatible)

The default tint is around 70% opacity, so the easiest is to use the target background color with 0.7 alpha component.

I've also noticed that this might reset to the default value if the visual effect contains a custom subview. If I add this same snippet to the viewDidLayoutSubviews function of the view's controller, then it will keep the custom background color even after the built-in subview is updated.

Here's an example with a dark blur effect style. The top part shows the default tint and the bottom version has a custom black background color with 70% opacity.

enter image description here

like image 96
Endanke Avatar answered Sep 27 '22 01:09

Endanke


If you just want the blur and your blurred view is gonna be stationary, you could use the UIImageEffects class and change the tintColor to a "full" white:

- (UIImage *)applyExtraLightEffect
{
    UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
    return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
}

As far as I know you can't change it in the UIVisualEffectView.

like image 24
lennartk Avatar answered Sep 27 '22 01:09

lennartk