iOS How to create a UIView that blur contents under itself [duplicate] - ios

This question already has answers here:
How can I produce an effect similar to the iOS 7 blur view?
(12 answers)
Closed 8 years ago.
I have a UIView that partially cover some contents and I would like apply a blur effect exactly like the iOS Notification Center.
I'm not looking for a way to apply blur on UIImage, but on UIView with other contents (UIView, UIButton, ecc) under it.
Ideas ?
Thanks.

First change the UIView into an UIImage.
You can use the following as a category of UIView.
#implementation UIView (ConvertToUIImage)
- (UIImage *)asImage {
NSAssert(self, #"Do not use this method on nil instance of UIView.");
if (!self) return 0;
UIGraphicsBeginImageContextWithOptions(self.frame.size, YES, 0);
[self drawViewHierarchyInRect:self.frame afterScreenUpdates:NO];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSAssert(image, #"Image must not be nil at this point.");
return image;
}
#end
Next you need to blur the UIImage, there is a related question here Creating a blur effect in iOS7
Finally, use the UIImage as a background.

myView.backgroundColor = [UIColor clearColor];
UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:myView.frame];
bgToolbar.barStyle = UIBarStyleDefault;
[myView.superview insertSubview:bgToolbar belowSubview:myView];
just past from an other answer how ever i use toolbar in my projects and works perfect, i am using alpha=0.98

Related

IOS Flaten a UIImageView in a UIVIew into a single UIView [duplicate]

This question already has answers here:
Capture UIView and Save as Image
(7 answers)
Closed 6 years ago.
I have a UIView that has another UIView and a UIImageView inside of it. I want to flaten the UIImage onto the UIView. If it helps you can think of the layout like this:
-UIView
---UIImageView
---UIView
How can I capture the whole UIView and save it as a single image?
You can use this to save your views as a single image.
-(UIImage *)visibleImage
{
UIGraphicsBeginImageContextWithOptions(yourview.frame.size, YES, [UIScreen mainScreen].scale);
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), CGRectGetMinX(yourview.frame) , CGRectGetMinY(yourview.frame));
[yourview.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img_FinalVisible = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img_FinalVisible;
}

Custom UINavigationBar with custom height in center

I have reviewed almost all questions on OS related to custom NavigationBar but unable to find those solutions helpful. Please have a look on following screenshot,
Red portion represents an icon (small image) in the center of navigationBar.
Please suggest some solution. Thanks in advance.
EDIT: I want to implement that for all UINavigationBar in app. I mean on each view
NOTE: I do not know who is down voting my question but i want to ask a question from those persons. Do you have any solution for my problem? If not, then why you are down voting my question? I will not be able to get help in this way. It's totally wrong.
You can subclass UINavigationBar.
#import "VSNavigationBar.h"
#interface VSNavigationBar ()
#property (nonatomic, weak) UIView *noseView;
#end
#implementation VSNavigationBar
-(void)layoutSubviews
{
[super layoutSubviews];
static CGFloat width = 80;
if (!_noseView) {
UIView *noseView = [[UIView alloc] initWithFrame:CGRectMake(self.bounds.size.width / 2 - width / 2, 0, width, width)];
self.noseView = noseView;
self.noseView.backgroundColor = self.barTintColor;
self.noseView.layer.cornerRadius = self.noseView.frame.size.width / 2;
[self addSubview:_noseView];
}
_noseView.frame = CGRectMake(self.bounds.size.width / 2 - width / 2, 0, width, width);
}
#end
And in your Storyboard you would select the NavigationController scene, in the tree view on the left select Navigation Bar and on the right side select the identity inspector and change the class to the subclass.
you need to create an image that looks like central part of the image you have provided and say -
UIImage *image = [UIImage imageNamed: #"logo.png"];
UIImageView *imageview = [[UIImageView alloc] initWithImage: image];
self.navigationItem.titleView = image view;
If you are trying to get circular effect like the bottom of the image you provided, in that case you need to have same image as above and set it as background image of navbar -
[navigationBar setBackgroundImage:[UIImage imageNamed: #"yourImage"] forBarMetrics:UIBarMetricsDefault];

Setting image background without repeat [duplicate]

This question already has answers here:
How to set background image of a view?
(7 answers)
Closed 8 years ago.
I have set my background to be an image with
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:[self.Images objectAtIndex:arc4random_uniform(4) ]]];
This worked instantly, and in effect the background changed between two images... until I changed something in the array that holds the images. Then suddenly the images are repeated in tiles all over the background.
What could cause something like this?
colorWithPatternImage: Is the key here, your using your image to create a pattern, not as a background. As logan has explained you need to re think how your setting your background. If you want to set your background from a random image maybe post a new question on how to do this
Here's something that should solve your problem, you can put it in viewDidLoad:
UIImageView * bgImageView = [[UIImageView alloc]init];
bgImageView.frame = self.view.bounds;
bgImageView.contentMode = UIViewContentModeScaleAspectFit;
bgImageView.image = [UIImage imageNamed:[self.Images objectAtIndex:arc4random_uniform(4)]];
self.view = bgImageView;
You can change/access it later by doing this:
UIImageView *bgImageView = (UIImageView *)self.view;
bgImageView.image = [UIImage imageNamed:[self.Images objectAtIndex:arc4random_uniform(4)]];
I ended up with the following solution:
1) Created a UIImageView in the interface builder AND dragged this out to fill the entire screen
2) Set the content of the imageView with this command:
imageView.image = [UIImage imageNamed:#"Themes.png"];
or if using an array:
imageView.image = [UIImage imageNamed:self.myArray[x]];
Where "x" is of course the number of the element in the array -1 (0 indexing)

Blur screen with iOS 7's snapshot API

I believe the NDA is down, so I can ask this question. I have a UIView subclass:
BlurView *blurredView = ((BlurView *)[self.view snapshotViewAfterScreenUpdates:NO]);
blurredView.frame = self.view.frame;
[self.view addSubview:blurredView];
It does its job so far in capturing the screen, but now I want to blur that view. How exactly do I go about this? From what I've read I need to capture the current contents of the view (context?!) and convert it to CIImage (no?) and then apply a CIGaussianBlur to it and draw it back on the view.
How exactly do I do that?
P.S. The view is not animated, so it should be OK performance wise.
EDIT: Here is what I have so far. The problem is that I can't capture the snapshot to a UIImage, I get a black screen. But if I add the view as a subview directly, I can see the snapshot is there.
// Snapshot
UIView *view = [self.view snapshotViewAfterScreenUpdates:NO];
// Convert to UIImage
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Apply the UIImage to a UIImageView
BlurView *blurredView = [[BlurView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)];
[self.view addSubview:blurredView];
blurredView.imageView.image = img;
// Black screen -.-
BlurView.m:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.imageView = [[UIImageView alloc] init];
self.imageView.frame = CGRectMake(20, 20, 200, 200);
[self addSubview:self.imageView];
}
return self;
}
Half of this question didn't get answered, so I thought it worth adding.
The problem with UIScreen's
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates
and UIView's
- (UIView *)resizableSnapshotViewFromRect:(CGRect)rect
afterScreenUpdates:(BOOL)afterUpdates
withCapInsets:(UIEdgeInsets)capInsets
Is that you can't derive a UIImage from them - the 'black screen' problem.
In iOS7 Apple provides a third piece of API for extracting UIImages, a method on UIView
- (BOOL)drawViewHierarchyInRect:(CGRect)rect
afterScreenUpdates:(BOOL)afterUpdates
It is not as fast as snapshotView, but not bad compared to renderInContext (in the example provided by Apple it is five times faster than renderInContext and three times slower than snapshotView)
Example use:
UIGraphicsBeginImageContextWithOptions(image.size, NULL, 0);
[view drawViewHierarchyInRect:rect];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Then to get a blurred version
UIImage* lightImage = [newImage applyLightEffect];
where applyLightEffect is one of those Blur category methods on Apple's UIImage+ImageEffects category mentioned in the accepted answer (the enticing link to this code sample in the accepted answer doesn't work, but this one will get you to the right page: the file you want is iOS_UIImageEffects).
The main reference is to WWDC2013 session 226, Implementing Engaging UI on iOS
By the way, there is an intriguing note in Apple's reference docs for renderInContext that hints at the black screen problem..
Important: The OS X v10.5 implementation of this method does not support the entire Core Animation composition model. QCCompositionLayer, CAOpenGLLayer, and QTMovieLayer layers are not rendered. Additionally, layers that use 3D transforms are not rendered, nor are layers that specify backgroundFilters, filters, compositingFilter, or a mask values. Future versions of OS X may add support for rendering these layers and properties.
The note hasn't been updated since 10.5, so I guess 'future versions' may still be a while off, and we can add our new CASnapshotLayer (or whatever) to the list.
Sample Code from WWDC ios_uiimageeffects
There is a UIImage category named UIImage+ImageEffects
Here is its API:
- (UIImage *)applyLightEffect;
- (UIImage *)applyExtraLightEffect;
- (UIImage *)applyDarkEffect;
- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;
- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius
tintColor:(UIColor *)tintColor
saturationDeltaFactor:(CGFloat)saturationDeltaFactor
maskImage:(UIImage *)maskImage;
For legal reason I can't show the implementation here, there is a demo project in it. should be pretty easy to get start with.
To summarize how to do this with foundry's sample code, use the following:
I wanted to blur the entire screen just slightly so for my purposes so I'll use the main screen bounds.
CGRect screenCaptureRect = [UIScreen mainScreen].bounds;
UIView *viewWhereYouWantToScreenCapture = [[UIApplication sharedApplication] keyWindow];
//screen capture code
UIGraphicsBeginImageContextWithOptions(screenCaptureRect.size, NO, [UIScreen mainScreen].scale);
[viewWhereYouWantToScreenCapture drawViewHierarchyInRect:screenCaptureRect afterScreenUpdates:NO];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//blur code
UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0];
UIImage *blurredImage = [capturedImage applyBlurWithRadius:1.5 tintColor:tintColor saturationDeltaFactor:1.2 maskImage:nil];
//or use [capturedImage applyLightAffect] but I thought that was too much for me
//use blurredImage in whatever way you so desire!
Notes on the screen capture part
UIGraphicsBeginImageContextWithOptions() 2nd argument is opacity. It should be NO unless you have nothing with any alpha other than 1. If you return yes the screen capture will not look at transparency values so it will go faster but will probably be wrong.
UIGraphicsBeginImageContextWithOptions() 3rd argument is the scale. Probably want to put in the scale of the device like I did to make sure and differentiate between retina and non-retina. But I haven't really tested this and I think 0.0f also works.
drawViewHierarchyInRect:afterScreenUpdates: watch out what you return for the screen updates BOOL. I tried to do this right before backgrounding and if I didn't put NO the app would go crazy with glitches when I returned to the foreground. You might be able to get away with YES though if you're not leaving the app.
Notes on blurring
I have a very light blur here. Changing the blurRadius will make it blurrier, and you can change the tint color and alpha to make all sorts of other effects.
Also you need to add a category for the blur methods to work...
How to add the UIImage+ImageEffects category
You need to download the category UIImage+ImageEffects for the blur to work. Download it here after logging in: https://developer.apple.com/downloads/index.action?name=WWDC%202013
Search for "UIImageEffects" and you'll find it. Just pull out the 2 necessary files and add them to your project. UIImage+ImageEffects.h and UIImage+ImageEffects.m.
Also, I had to Enable Modules in my build settings because I had a project that wasn't created with xCode 5. To do this go to your target build settings and search for "modules" and make sure that "Enable Modules" and "Link Frameworks Automatically" are both set to yes or you'll have compiler errors with the new category.
Good luck blurring!
Check WWDC 2013 sample application "running with a snap".
The blurring is there implemented as a category.

Center [UIColor colorWithPatternImage]?

I couldn't find anything on how you can center the 'image' when you use (maybe you can't):
[self setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background"]]];
Setting my [self setContentMode:UIContentModeCenter]; doesnt help.
Do I have to manually draw the image (either in drawRect or set the content of the CALayer? Which one if preferable?
I think you're on the wrong path here: you create a UIColor from a pattern (pattern already implies this is a repeating image). All in all- you can't have your pattern not repeat and centered.
If you just want simple image as background of your UIView, just add it as a subview and center it.
UIImage* img = [UIImage imageNamed:#"yourfile.png"];
UIImageView* imgView = [[UIImageView alloc]initWithImage: img];
[yourUIView addSubview: imgView];
imgView.center = CGPointMake(yourUIView.frame.size.width/2, yourUIView.frame.size.height/2);
Now - add more subviews to your "yourUIView" view and they'll show on top of the image - thus the image becoming the background.
So... no need to draw anything yourself.

Resources