iOS - Creating a blurred layer using CALayer - ios

I created a CALayer with white color and 0.4 of opacity. What I want to is to make this layer above an image and make it blur, like the notification layer is blurring on the app or the home screen you're opening here's my CALayer:
CALayer *lyr = [CALayer layer];
lyr.bounds = CGRectMake(0, 0, 190, 190);
lyr.position = CGPointMake(90, 50);
lyr.backgroundcolor = [UIColor whiteColor].CGColor;
lyr.opacity = 0.4f;
[self.view.layer addSubLayer:lyr];
Sorry if I didn't explained what I need exactly
Thanks in Advance

Take a look at FXBlurView
https://github.com/nicklockwood/FXBlurView
It also provides a method to apply a tinted blur on an image.
- (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)iterations tintColor:(UIColor *)tintColor;
-> Import UIImage+FXBlurImage.h

Related

Disable preview layer when recording on camera

I am using https://github.com/chroman/HeartBeats to draw heartbeat's linechart. But, i want to remove preview layer (or disable it) and only display "linechart" on my own UIView, but i dont know where to edit.
im a beginer at iOS-dev, pls cmt if you know. thank you.
edit 1: i think CALayer is my issue. (on viewDidLoad):
imageLayer = [CALayer layer];
imageLayer.frame = self.view.layer.bounds;
imageLayer.contentsGravity = kCAGravityResizeAspectFill;
[self.view.layer addSublayer:imageLayer];
[self setupAVCapture];
edit 2: note: red backgroud is your finger when place on it. if not, it will show what camera currently recording.
try to set background color as clear color or black color to your layer something like,
imageLayer = [CALayer layer];
imageLayer.backgroundColor = [UIColor clearColor].CGColor;
or
imageLayer.backgroundColor = [UIColor blackColor].CGColor;

CALayer draw outside of rect

I'm using this code to add a layer to a custom UIView and it works like a charm:
CGRect newrect = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
CALayer* heartBackground = [CALayer layer];
heartBackground.contents = (__bridge id)([UIImage imageNamed:#"5HeartsGray"].CGImage);
heartBackground.frame = newrect;
[self.layer addSublayer:heartBackground];
But when I tried to use it in draw method using Quartz using a new Rect(like this)
CGContextSaveGState(context);
CGRect ratingRect = CGRectMake(250, 100, 150, 20);
CALayer* heartBackground = [CALayer layer];
heartBackground.contents = (__bridge id)([UIImage imageNamed:#"5HeartsGray"].CGImage);
heartBackground.frame = ratingRect;
[heartBackground renderInContext:context];
CGContextRestoreGState(context);
It renders in the beginning of the frame and not inside of ratingRect.
If I call [heartBackground setNeedsDisplay] it disappear. The same thing with heartBackground.masksToBounds = YES
What I'm doing wrong. Do I need To switch to CGLayer because I'm using CoreGraphics?
This is the output when working with CoreGraphics (as you see the hearts starts at coordinates x=0, y=0 and normally it starts at x=250, y=100):
It doesn't make sense to create and draw a CALayer inside draw function of a UIView. CALayer is an independently drawable unit and it draws itself on its parentLayer's context by default. Which means if you really want to use separate CALayers try adding as many subLayers to self.layer (inside a UIView) as you want, set their frames and they'll get drawn when their container view shows up. Regarding your problem, here's what you can try.
Option 1: Take this code
CGRect ratingRect = CGRectMake(250, 100, 150, 20);
CALayer* heartBackground = [CALayer layer];
heartBackground.contents = (__bridge id)([UIImage imageNamed:#"5HeartsGray"].CGImage);
heartBackground.frame = ratingRect;
[self.layer addSubLayer:heartBackground];
Out of the drawRect: method and write it in initWithFrame: and in drawRect simply do [heartBackground renderInContext:UIGraphicsGetCurrentContext];
Option 2: Draw your hearts without a CALayer.
CGRect ratingRect = CGRectMake(250, 100, 150, 20);
[[UIImage imageNamed:#"5HeartsGray"] drawInRect:ratingRect];

CALayer - How do I create an image with a solid background and transparent text?

I'm trying to create movie generation application by using AVComposition and have a trouble in making title frame.
Each frame is actually a calayer and title layer is on top of other frames.
Title(Text) needs to be transparent with black background so that they can see some part of the first content frame under title text letters.
I searched most articles about calayer mask, but nothing helped me.
I thought this article (How to make only the part covered by text/title transparent in a UIView in IOS) is helpful and coded like Dave's way, but got only white screen.
Here is what I have done:
// create UILabel from the title text
CGRect rectFrame = CGRectMake(0, 0, videoSize.width, videoSize.height);
UILabel *lbTitle = [[UILabel alloc] initWithFrame:rectFrame];
lbTitle.text = self.titleText;
lbTitle.font = [UIFont fontWithName:#"Helvetica" size:60];
lbTitle.textColor = [UIColor blackColor];
lbTitle.backgroundColor = [UIColor whiteColor];
// get title image and create mask layer
UIGraphicsBeginImageContextWithOptions(lbTitle.bounds.size, TRUE, [[UIScreen mainScreen] scale]);
[lbTitle.layer renderInContext:UIGraphicsGetCurrentContext()];
CGImageRef viewImage = [UIGraphicsGetImageFromCurrentImageContext() CGImage];
UIGraphicsEndImageContext();
CALayer *maskLayer = [CALayer layer];
maskLayer.contents = (__bridge id)viewImage;
maskLayer.frame = rectFrame;
// create title background layer and set mastLayer as mast layer of this layer
// this layer corresponds to "UIView's layer" in Dave's method
CALayer *animatedTitleLayer = [CALayer layer];
animatedTitleLayer.backgroundColor = [UIColor whiteColor].CGColor;
animatedTitleLayer.mask = maskLayer;
animatedTitleLayer.frame = rectFrame;
...
[view.layer addSubLayer:animatedTitleLayer];
Here I used animatedTitleLayer as title background(black background), but what I see is white screen.
Anyone can help me? Thanks in advance.
The mask uses the alpha channel to determine what parts to mask out and what parts to keep. However, your label that you render into an image is rendered as black text on a white background so there is no transparency in the image.
You have also specified that the graphics context you are using to render the image is opaque so even if the background color of the label as was clear you would get an opaque image.
So you need to set a clear background color on the label and pass NO as the second argument when you create the graphics context.

Drawing sprites programatically for sprite kit with alpha channel?

I'm trying to prototype an app for sprite kit, and it would be advantageous to me to be able to draw the sprites I need programatically for now, and then make actual sprites later. I've made a rough circle, and when I convert to a UIImage (or CGImage) using renderInContext, it shows up on the sprite view with a black background, ignoring the alpha channel, apparently. If I add the UIImage to a regular view as a UIImageView, the alpha channel is rendered properly. I was wondering what I'm doing wrong, or if theres' a workaround for this.
float rockSize = 100;
UIView* drawingView = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];
drawingView.backgroundColor = [UIColor clearColor];
CALayer* circleLayer = [CALayer layer];
circleLayer.frame = CGRectMake(0,0,rockSize,rockSize);
circleLayer.backgroundColor = [Utils getTiledColorFromColor:[UIColor purpleColor]].CGColor;
circleLayer.cornerRadius = rockSize/2.0;
circleLayer.masksToBounds = YES;
[drawingView.layer addSublayer:circleLayer];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(rockSize, rockSize), NO, [UIScreen mainScreen].scale);
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor clearColor].CGColor);
CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0,0,rockSize,rockSize));
[drawingView.layer renderInContext: UIGraphicsGetCurrentContext()];
UIImage *layerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
SKSpriteNode *rockNode = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImage:layerImage]];
CGPoint position = CGPointMake(200,100);
rockNode.position = position;
[self addChild:rockNode];
Such an affect when you see black view background frequently happens when the view has opaque property incorrectly set to YES without actually being opaque (usually this happens when the view is created programmatically, opaque = YES is default).
You can fix this for example by setting opaque to NO.

Darken view as if disabled

How do you darken a view as if it were disabled/highlighted, preferably without using any additional views?
By view I mean a UIView, with all its children. I want to achieve the same effect of a disabled/highlighted UIButton.
Do not assume that the view is fully opaque.
What I'm currently playing with:
Create a black layer with opacity (_highlightLayer). This is similar to the "black view with alpha" approach.
Mask _highlightLayer with an non-opaque image of the original view.
Add the _highlightLayer to the view's layer.
Only the non-transparent pixels of the view will be darkened.
The code:
- (void)highlight
{
// Black layer with opacity
_highlightLayer = [CALayer layer];
_highlightLayer.frame = CGRectMake(0, 0, self.layer.bounds.size.width, self.layer.bounds.size.height);
_highlightLayer.backgroundColor = [UIColor blackColor].CGColor;
_highlightLayer.opacity = 0.5;
// Create an image from the view
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *maskImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Create a mask layer for the black layer
CALayer *maskLayer = [CALayer layer];
maskLayer.contents = (__bridge id) maskImage.CGImage;
maskLayer.frame = _highlightLayer.frame;
_highlightLayer.mask = maskLayer;
[self.layer addSublayer:_highlightLayer];
}
And then:
- (void)unhighlight
{
[_highlightLayer removeFromSuperlayer];
_highlightLayer = nil;
}
Of course, this should only be used for small views.
Example:
You have a UIButton *button1 and UIView *view1
You can disable a button and a view in this way:
[view1 setHidden:YES];
[button1 setEnabled:NO];
Enabling a button and a view can be done this way:
[view1 setHidden:NO];
[button1 setEnabled:YES];
Hope this helps..
While this approach fails to meet your preference of not using additional views, simply adding a black view with alpha of 0.6 or so seems to achieve the effect, with the added benefit that you can use this new view to intercept UIEvents so that all the subviews are effectively disabled en masse.
You can even get graphically fancy and instead of just using a black background for the overlaid view, you can fill its background with a radial gradient to achieve the sort of spotlighted effect that happens in iOS when a popup view disables the view behind it...

Resources