I looked at this: How to use UIVisualEffectView? but I don't really understand how to apply it to my situation, after even looking at the comments.
I have a class SpecialHUD which is a subclass of HUDView which is a subclass of UIView. HUDView has its layer.contents set to be a background image (certain rectangle with rounded edges), and text in a label added as a subview. I can't change HUDView. I only need to change SpecialHUD.
I want the background image to act as the thing that blurs whatever is behind it - I can't get rid of the background image.
How do I use the UIVisualEffectView with my SpecialHUD?
I tried adding this to an update method in my SpecialHUD:
UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = self.bounds;
[self addSubview:visualEffectView];
[[visualEffectView contentView] addSubview:self.label];
But it blurs everything in the rectangular container, and disregards the image — I'm not sure how to make everything work together.
Related
I am trying to create blur effect on the UIView as well as I want to add vibrancy Effect so that I can highlight my buttons and use them. I am trying to learn via apple docs and couple of tutorials but unable to get in the following steps I am doing are correct.
Steps 1. I am creating a blur view adding it as subview to present view so that it looks blur.
Step 2 . Then i am creating a vibrancy view for the blur effect and adding it to contentview of blurview.
But i am unable to get the blur effect, can anyone help me to understand
1. If the following steps are correct.
2. If not how should ideally the sequence be.
3. How to highlight those buttons and use them. ( I am attaching the snaphot of my storyboard too).
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIBlurEffect *blurEffect= [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];
UIVisualEffectView *blurView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
[blurView setUserInteractionEnabled:false];
[self.view addSubview:blurView];
UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
UIVisualEffectView *vibrancyView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
[vibrancyView setTranslatesAutoresizingMaskIntoConstraints:NO];
//[vibrancyView.contentView addSubview:s];
[blurView.contentView addSubview:vibrancyView];
}
The chief problem with your code is that you have neglected to give your blur view any size. Therefore it has zero size. Thus you will not see it do anything; it is, in effect, invisible. The most it can blur would be a single pixel behind it, and you are unlikely to notice that.
You are not setting the frame for your blurView and vibrancyView.
blurView.frame = self.view.frame;
vibrancyView.frame = self.view.frame;
I want to place the image view on background of window,above the image view i have placed the table view which is transparent.I want image in background is to be blur. thanks..
In iOS 8 you can use UIVisualEffect to blur views
UIVisualEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];// explore other effects too
UIVisualEffectView *visualEffectView =[[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = YOURFRAME; // set frame
[visualEffectView setAlpha:1.0];// set as you like
[YOURVIEW addSubview:visualEffectView]; //add on your view where you want
I am trying to present a view with a blurred transparent background over an existing view. I am able to get the desired effect during the presentation animation, but once the blurred view is fully presented, it becomes opaque.
Here's how I am presenting it:
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
blurEffectView.frame = self.view.bounds;
[blurEffectView setOpaque:NO];
[self.view insertSubview:blurEffectView atIndex:0];
[blurEffectView setTranslatesAutoresizingMaskIntoConstraints:false];
}
In my blurred view, I have set the background color to clear color and opaque to NO. Any thoughts?
Note that any UIVisualEffectView with a UIBlurEffect will be opaque if the "Reduce Transparency" accessibility setting is on.
(Settings > General > Accessibility > Increase Contrast > Reduce Transparency)
(Which is what your are actually checking with your if (!UIAccessibilityIsReduceTransparencyEnabled()) statement.)
I wound up writing a custom presentation controller. Never found a way to do this with standard presentations.
In the view where I want the effect viewDidLoad:
//Custom Modal Presentation
[self setModalPresentationStyle:UIModalPresentationCustom];
//blur the controlContainerView
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:[self blurStyle]];
UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
blurEffectView.frame = self.controlContainerView.bounds;
[blurEffectView setOpaque:NO];
[self.controlContainerView insertSubview:blurEffectView atIndex:0];
[blurEffectView setTranslatesAutoresizingMaskIntoConstraints:false];
}
Invoking the above view:
//in .h
#property (nonatomic) id<UIViewControllerTransitioningDelegate> transitioningDelegate;
//In .m
BlurViewController *blurVC = [self.storyboard instantiateViewControllerWithIdentifier:#"blurView"];
_transitioningDelegate = [[MyCustomOverlayDelegate alloc] init];
[blurView setModalPresentationStyle:UIModalPresentationCustom];
[blurView setTransitioningDelegate:[self transitioningDelegate]];
[blurView setBlurStyle:UIBlurEffectStyleLight];
[self presentViewController: blurView animated:YES completion:nil];
You will also need to import the entire stack of presentation controller classes. For me, these were OverlayDelegate, OverlayTransitionAnimator, and OverlayPresentationController. This is where the real work is.
If you can, check out WWDC 2014 session 228 "A look inside presentation controllers". Custom presentations are covered about half-way through. It was what I used to base my custom stack on and reasonably straight forward.
From the documentation:
A UIBlurEffect object applies a blurring effect to the content layered behind a UIVisualEffectView.
So I think the problem is your clear backgroundColor. If you have some kind of content or coloring behind your UIVisualEffectView, it should work.
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];
UIVisualEffectView *blurredView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
This simple code snippet does work for me. In the ViewController I want to show the blurred effect I just call [[self view] addSubView:blurredView]
Simply set the view controller which holds the blurred view like this:
myViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
It prevents optimisation which removes views from the view hierarchy which in turn makes the blurred view presented first and thus making it opaque.
I have a UIVisualEffectView which is causing some strange artefacts right when it appears. The UIVisualEffectView is added in code after the view loads because it's not available in iOS 7.
Look at the blurred text background over the street view image: http://s.swic.name/Z3UL
The blur takes a good 0.1 seconds to appear, and before that it's just a lower resolution background shining through like the blur hasn't been calculated yet.
Any idea what is going on? I'm adding the blur in awakeFromNib using this code
- (void)addBlurWithColor:(UIColor *)color andStyle:(UIBlurEffectStyle)style andVibrancy:(BOOL)vibrancy
{
if (UIDevice.supportsVisualEffects && NSClassFromString(#"UIVisualEffectView") && !UIAccessibilityIsReduceTransparencyEnabled()) {
self.backgroundColor = color;
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:style];
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = self.bounds;
visualEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
NSArray *subviews = self.subviews;
[self addSubview:visualEffectView];
[self sendSubviewToBack:visualEffectView];
if (vibrancy) {
UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
UIVisualEffectView *vibrancyEffectView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
[vibrancyEffectView setFrame:self.bounds];
vibrancyEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
for (UIView *subview in subviews) {
[vibrancyEffectView.contentView addSubview:subview];
}
[[visualEffectView contentView] addSubview:vibrancyEffectView];
}
}
}
Edit: The video just has slow animations enabled, the transition is a regular push segue.
Edit2: I get the same strange behaviour if i just drag drop a "UIVisualEffectView with Blur" in Interface Builder, so the code above shouldn't be to blame.
Found the problem, when the view appears I'm reloading the tableview inside [UIView transitionWithView:...] which alters the alpha which apparently is a big no-no when it comes to UIVisualEffectViews!
According to UIVisualEffectView Documentation;
When using the UIVisualEffectView class, avoid alpha values that are
less than 1. Creating views that are partially transparent causes the
system to combine the view and all the associated subviews during an
offscreen render pass. UIVisualEffectView objects need to be combined
as part of the content they are layered on top of in order to look
correct. Setting the alpha to less than 1 on the visual effect view or
any of its superviews causes many effects to look incorrect or not
show up at all.
https://developer.apple.com/library/ios/documentation/uikit/reference/UIVisualEffectView/index.html
Could someone give a small example of applying the blur to an image? I've been trying to figure out the code for a while now :( still new at obj c!
The UIVisualEffectView provides a simple abstraction over complex
visual effects. Depending on the desired effect, the results may
affect content layered behind the view or content added to the view’s
contentView.
Apply a UIVisualEffectView to an existing view to apply a blur or
vibrancy effect to the exiting view. After you add the
UIVisualEffectView to the view hierarchy, add any subviews to the
contentView of the UIVisualEffectView. Do not add subviews directly to
the UIVisualEffectView itself.
https://developer.apple.com/documentation/uikit/uivisualeffectview#//apple_ref/occ/instp/UIVisualEffectView/contentView
Just put this blur view on the imageView. Here is an example in Objective-C:
UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = imageView.bounds;
[imageView addSubview:visualEffectView];
and Swift:
var visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .Light))
visualEffectView.frame = imageView.bounds
imageView.addSubview(visualEffectView)
Here is how to use UIVibrancyEffect and UIBlurEffect with UIVisualEffectView
Objective-C:
// Blur effect
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
[blurEffectView setFrame:self.view.bounds];
[self.view addSubview:blurEffectView];
// Vibrancy effect
UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
UIVisualEffectView *vibrancyEffectView = [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
[vibrancyEffectView setFrame:self.view.bounds];
// Label for vibrant text
UILabel *vibrantLabel = [[UILabel alloc] init];
[vibrantLabel setText:#"Vibrant"];
[vibrantLabel setFont:[UIFont systemFontOfSize:72.0f]];
[vibrantLabel sizeToFit];
[vibrantLabel setCenter: self.view.center];
// Add label to the vibrancy view
[[vibrancyEffectView contentView] addSubview:vibrantLabel];
// Add the vibrancy view to the blur view
[[blurEffectView contentView] addSubview:vibrancyEffectView];
Swift:
// Blur Effect
let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
view.addSubview(blurEffectView)
// Vibrancy Effect
let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect)
let vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect)
vibrancyEffectView.frame = view.bounds
// Label for vibrant text
let vibrantLabel = UILabel()
vibrantLabel.text = "Vibrant"
vibrantLabel.font = UIFont.systemFont(ofSize: 72.0)
vibrantLabel.sizeToFit()
vibrantLabel.center = view.center
// Add label to the vibrancy view
vibrancyEffectView.contentView.addSubview(vibrantLabel)
// Add the vibrancy view to the blur view
blurEffectView.contentView.addSubview(vibrancyEffectView)
You can also use the interface builder to create these effects easily for simple situations. Since the z-values of the views will depend on the order they are listed in the Document Outline, you can drag a UIVisualEffectView onto the document outline before the view you want to blur. This automatically creates a nested UIView, which is the contentView property of the given UIVisualEffectView. Nest things within this view that you want to appear on top of the blur.
You can also easily take advantage of the vibrancy UIVisualEffect, which will automatically create another nested UIVisualEffectView in the document outline with vibrancy enabled by default. You can then add a label or text view to the nested UIView (again, the contentView property of the UIVisualEffectView), to achieve the same effect that the "> slide to unlock" UI element.
I prefer creating Visual Effects via Storyboard - no code used for creating or maintaining UI Elements. It gives me full landscape support, too. I have made a little demo of using UIVisualEffects with Blur and also Vibrancy.
Demo on Github
If anyone would like the answer in Swift :
var blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark) // Change .Dark into .Light if you'd like.
var blurView = UIVisualEffectView(effect: blurEffect)
blurView.frame = theImage.bounds // 'theImage' is an image. I think you can apply this to the view too!
Update :
As of now, it's available under the IB so you don't have to code anything for it :)
-(void) addBlurEffectOverImageView:(UIImageView *) _imageView
{
UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = _imageView.bounds;
[_imageView addSubview:visualEffectView];
}