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 choosa
You can add a UIBlurEffect over the image. And that will do the trick.
Here is an example of a UIImageView with blur effect on it. Remember to add a Image to the UIImageView.
Adjust blur amount with blurEffectView.alpha = 0.8 (from 0 to 1)
import UIKit
class BlurEffectImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
addBlurEffect()
}
private func addBlurEffect(){
let blurEffect = UIBlurEffect(style: .light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.alpha = 0.8
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
blurEffectView.translatesAutoresizingMaskIntoConstraints = false
addSubview(blurEffectView)
NSLayoutConstraint(item: blurEffectView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: blurEffectView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: blurEffectView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: blurEffectView, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 1.0, constant: 0).isActive = true
}
}
Add a BlurEffectView to a view with view's alpha < 1
func addBlurEffectView() -> Void {
if !UIAccessibilityIsReduceTransparencyEnabled() {
let viewContainer = UIView()
viewContainer.frame = self.view.bounds
viewContainer.alpha = 0.5
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.layer.zPosition = -0.5;
blurEffectView.frame = self.view.bounds;
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
viewContainer.addSubview(blurEffectView)
self.view.addSubview(viewContainer)
self.view.sendSubview(toBack: viewContainer)
}
}
A solution similar to some here, but simpler, is to use a UIViewPropertyAnimator (iOS 10+) and set its fractionComplete
property to some value between 0 and 1.
// add blur view to image view
let imgBlur = UIVisualEffectView()
imgView.addSubview(imgBlur)
imgBlur.frame = imgView.bounds
// create animator to control blur strength
let imgBlurAnimator = UIViewPropertyAnimator()
imgBlurAnimator.addAnimations {
imgBlur.effect = UIBlurEffect(style: .dark)
}
// 50% blur
imgBlurAnimator.fractionComplete = 0.5
Note, if you plan to vary fractionComplete
based on a pan gesture, scroll view, slider, etc. you'll want to set pausesOnCompletion = true
(iOS 11+).
I use UIVisualEffectView like this to get adjustable blur circles. The blur level is controlled by a slider that controls the alpha. I'll include the slider handler below too. The blur circle size is adjustable with pinch spread action. I will include that too. And you can drag around the blur circles. I'll leave that as an exercise for the reader. If you want a blur rectangle, just don't round the corners. To see this blur circle design in action, load the MemeSoEasy app (free), add a photo (that you can put a blur circle on top of), then add a blur circle.
UIVisualEffectView *blurVisualEffectView;
UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
blurVisualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
blurVisualEffectView.frame = lastChosenBlurCircleRect;
blurVisualEffectView.center = CGPointMake(halfScreenX, halfScreenY);
[self.view addSubview:blurVisualEffectView];
CGFloat blurCornerRadius = blurVisualEffectView.bounds.size.width/2;
[[blurVisualEffectView layer]setCornerRadius:blurCornerRadius];
[[blurVisualEffectView layer]setMasksToBounds:YES];
[[blurVisualEffectView layer] setBorderWidth:4.0f];
[[blurVisualEffectView layer] setBorderColor:[UIColor blueColor].CGColor];
blurVisualEffectView.userInteractionEnabled = NO;
blurVisualEffectView.alpha = 0.97;
[blurArray addObject:blurVisualEffectView];
Slider handler :
Note that I store my blur objects in an array, so I can let users create as many as desired. The slider handler works on the last object in the array. The slider min and max values are 0.0 and 1.0
UISlider *slider_ = (UISlider *)sender;
CGFloat ourSliderValue = slider_.value;
UIVisualEffectView *currentBlurObject =
[blurArray objectAtIndex:blurArray.count - 1];
currentBlurObject.alpha = ourSliderValue;
Size change handler for pinch spread
int changeInWidth = 0; // one pixel at a time
if (pinchGesture.scale > 1.0) {
changeInWidth++;
}
if (pinchGesture.scale < 1.0) {
changeInWidth--;
}
UIVisualEffectView *currentBlurObject =
[blurArray objectAtIndex:blurArray.count - 1];
CGPoint oldCenter = currentBlurObject.center;
currentBlurObject.frame = CGRectMake(0, 0, currentBlurObject.frame.size.width + changeInWidth, currentBlurObject.frame.size.width + changeInWidth);
currentBlurObject.center = oldCenter;
lastChosenBlurCircleRect = currentBlurObject.frame;
CGFloat blurCornerRadius = currentBlurObject.frame.size.width/2;
[[currentBlurObject layer]setCornerRadius:blurCornerRadius];
HUGE THANKS TO mitja13, I make the Objective-C Version.
NS_ASSUME_NONNULL_BEGIN
@interface UIView (Gaoding)
- (void)gd_pauseAnimationsWithDelay:(double)delay;
- (void)gd_resumeAnimations;
@end
NS_ASSUME_NONNULL_END
@implementation UIView (Gaoding)
- (void)gd_pauseAnimationsWithDelay:(double)delay {
double time = delay + CFAbsoluteTimeGetCurrent();
__block CALayer *layer = self.layer;
CFRunLoopRef runloopRef = CFRunLoopGetCurrent();
CFRunLoopAddTimer(runloopRef, CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, time, 0, 0, 0, ^(CFRunLoopTimerRef timer) {
double pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0;
layer.timeOffset = pausedTime;
layer = nil;
CFRunLoopRemoveTimer(runloopRef, timer, kCFRunLoopCommonModes);
CFRelease(timer);
timer = NULL;
}), kCFRunLoopCommonModes);
}
- (void)gd_resumeAnimations {
CALayer *layer = self.layer;
double pausedTime = layer.timeOffset;
layer.speed = 1;
layer.timeOffset = 0.0;
layer.beginTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
}
@end
How to Use:
/// SHOW IT
UIVisualEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *blurEffectView = UIVisualEffectView.new;
// .... something other
[UIView animateWithDuration:0.35 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
blurEffectView.effect = effect;
}];
[blurEffectView gd_pauseAnimationsWithDelay:0.1]; // 0.1/0.35 = 28.57% blur of UIBlurEffectStyleLight
// .... something other
/// HIDE IT
[blurEffectView gd_resumeAnimations];
[UIView animateWithDuration:0.35 delay:0 options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState animations:^{
blurEffectView.effect = nil;
}];