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

2

7

Currently, I'm using a UIVisualEffectView to apply a blur to an image.

I have a UIScrollView. As I pull down on the scrollView, in my "scrollViewDidScroll" method, I'm changing the alpha of the UIVisualEffectView. The current behavior of this is that the blur radius changes smoothly as I drag around in the view.

The problem is, of course, I'm not supposed to be doing this. Getting warnings about changing the alpha value of a UIVisualEffectView.

I've seen people say to do a smooth transition of blurring using an animation, like this here: How to fade a UIVisualEffectView and/or UIBlurEffect in and out?

However, I haven't seen anything that allows me to do this during, say a pan-gesture or something. I mean, if I set up an animation with a timed amount, all good. But doing this during a drag?

Sherd answered 31/8, 2016 at 19:38 Comment(0)
R
9

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.
Retroflex answered 1/9, 2016 at 7:7 Comment(6)
Thanks for this. This was just what I was looking for!Sherd
:D An additional note: sometimes it seems the animation won't work until the UIVisualEffectView subview is added to the view hierarchy. I usually instantiate and add the blur in viewDidLoad and add the animation later in viewDidAppear:.Retroflex
I'm using the same method in Swift. However, there is a bug - when the app moves to the background, and then comes back, the animation automatically reaches its end state and doesn't animate anymore. Have you guys came around that issue? Do you have an idea how to work around that?Congregate
@Congregate you may need to prevent the animation from being getting removed?Retroflex
@Retroflex I implemented a workaround and so far it seems to be working. To make it simple: when the app goes to the background I'm saving the UITableView's contentOffset.y, and when it comes back to the foreground I restart the animation and set the UITableView's contentOffset to the saved position. It all happens very smoothly. I know it's not the best solution but I haven't found anything better yet, been looking for a solution for days.Congregate
For future visitors: UIViewPropertyAnimator is a better way to do this. See this answer: https://mcmap.net/q/447583/-how-to-edit-the-uiblureffect-intensityBrufsky
M
0

While the solution by @DanMorrow works, I came across a strange problem: When the ViewController that uses this solution presents another model ViewController, the app becomes unresponsive.

This problem went away, as soon I removed the line self.blurredEffectView.layer.speed = 0;. It's strange, that setting the layer speed of some subview influences a model ViewController presendet by this ViewController. Howerver, in my case this was clearly the source of the problem.

As @mattsven pointed out in his comment there is another solution using an UIViewPropertyAnimator which can be found in this answer in this answer . This solutions seems to be less hacky and it does not lead to the problem described above.

Miun answered 22/3, 2023 at 11:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.