Animating the fractional part of the UIViewPropertyAnimator to blur the background

So, I am using the new UIViewPropertyAnimator and UIVisualEffectView to achieve the same as Spotlight search when scrolling on the home screen and it blurs the background.

I am using the fractionComplete property to set the procent as blur when panning a UIView.

    animator = UIViewPropertyAnimator(duration: 1, curve: .linear) {
        self.blurEffectView.effect = nil
    }

      

And the amount of blur changes with a value between 0.0 - 1.0.

        animator?.fractionComplete = blurValue

      

But when I undo the panorama gesture, I want the blur to animate backwards from where there is no blur (e.g. ~ โ†’ 1.0) with a duration of about 0.4 milliseconds.

Right now I just set the fractionComplete to 1.0 when the panorama gesture is canceled. Instead, I want to bring it to life.
I've tried UIView.animate (withDuration .. but it doesn't affect the UIViewPropertyAnimators fractionComplete and that's the only way to blur the UIVisualEffectView.

Any ideas?

+2


source to share


2 answers


Seems to fractionComplete

have an error (my Stackoverflow question: UIViewPropertyAnimator does not update the view when it waits ), rdar: // 30856746 . The property only sets the state from inactive

to active

, but does not update the view because (I assume) there is some other internal state that does not start.

To fix the problem, you can do this:

animator.startAnimation() // This will change the `state` from inactive to active
animator.pauseAnimation() // This will change `isRunning` back to false, but the `state` will remain as active

// Now any call of `fractionComplete` should update your view correctly!
animator.fractionComplete = /* your value here */

      



Here's a snippet of the playground:

let liveView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 50))
liveView.backgroundColor = .white

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = liveView

let square = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
square.backgroundColor = .red

liveView.addSubview(square)

let animator = UIViewPropertyAnimator.init(duration: 5, curve: .linear)

animator.addAnimations {

    square.frame.origin.x = 350
}

let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
blurView.frame = liveView.bounds

liveView.addSubview(blurView)

animator.addAnimations {

    blurView.effect = nil
}

// If you want to restore the blur after it was animated, you have to 
// safe a reference to the effect which is manipulated
let effect = blurView.effect

animator.addCompletion {
    // In case you want to restore the blur effect
    if $0 == .start { blurView.effect = effect }
}

animator.startAnimation()
animator.pauseAnimation()

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {

    animator.fractionComplete = 0.5
}

DispatchQueue.main.asyncAfter(deadline: .now() + 4) {

    // decide the direction you want your animation to go.
    // animator.isReversed = true
    animator.startAnimation()
}

      

+10


source


If you're still looking for a way to actually animate fractionComplete without using a slider or gesture, I was quite happy with my results using CADisplayLink. You can see my results here: https://gist.github.com/vegather/07993d15c83ffcd5182c8c27f1aa600b



+2


source







All Articles