Less Blur with `Visual Effect View with Blur`?

Travis Griggs picture Travis Griggs · Apr 7, 2015 · Viewed 37k times · Source

Title pretty much asks it all...

I'm playing with the iOS8 Visual Effect View with Blur. It's over a UIImageView that shows a user choosable background photo. The view placed in the contentView itself is my own custom view, shows a sort of graph/calendar. Most of said calendar graph is transparent. The blur it applies to the photo behind it is really heavy. I'd like to let more of the detail leak through. But Apple only seems to give three canned values:

typedef enum {
    UIBlurEffectStyleExtraLight,
    UIBlurEffectStyleLight,
    UIBlurEffectStyleDark 
} UIBlurEffectStyle;

I've monkied around with different alphas and background colors of the UIVisualEffectView (even though the documentation warns against that), but that doesn't do anything but make it worse.

Answer

mitja13 picture mitja13 · Jun 1, 2016

It's a pity that Apple did not provide any options for blur effect. But this workaround worked for me - animating the blur effect and pausing it before completion.

func blurEffectView(enable enable: Bool) {
    let enabled = self.blurView.effect != nil
    guard enable != enabled else { return }

    switch enable {
    case true:
        let blurEffect = UIBlurEffect(style: .ExtraLight)
        UIView.animateWithDuration(1.5) {
            self.blurView.effect = blurEffect
        }

        self.blurView.pauseAnimation(delay: 0.3)
    case false:
        self.blurView.resumeAnimation()

        UIView.animateWithDuration(0.1) {
            self.blurView.effect = nil
        }
    }
}

and the UIView extensions for pausing (with a delay) and resuming view's animation

extension UIView {

    public func pauseAnimation(delay delay: Double) {
        let time = delay + CFAbsoluteTimeGetCurrent()
        let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, time, 0, 0, 0, { timer in
            let layer = self.layer
            let pausedTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
            layer.speed = 0.0
            layer.timeOffset = pausedTime
        })
        CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes)
    }

    public func resumeAnimation() {
        let pausedTime  = layer.timeOffset

        layer.speed = 1.0
        layer.timeOffset = 0.0
        layer.beginTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime
    }
}