I have a UIViewController with a UIImageView (imageView), and I'm defining several layers that will be nested in the imageview as follows in viewDidLoad:
//container layer - the very top layer
CALayer *containerLayer = [CALayer layer];
containerLayer.opacity = 0;
containerLayer.bounds = [self.imageView.layer frame];
// Holder Layer
CALayer *holderLayer = [CALayer layer];
holderLayer.opacity = 0;
holderLayer.bounds = self.imageView.bounds;
// Hierarchy layers
[containerLayer setValue:holderLayer forKey:#"__holderLayer"];
[containerLayer addSublayer:holderLayer];
[self.imageView.layer addSublayer:containerLayer];
I have the following code that works when loading an image from a UIImagePicker :
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageView *newImgView = [[UIImageView alloc] initWithFrame:self.imageView.frame];
CGRect frame = self.imageView.frame;
newImgView.image = image;
frame.origin = CGPointMake(0, 0);
newImgView.layer.frame = frame;
newImgView.layer.opacity = .9;
newImgView.layer.contentsGravity = kCAGravityResizeAspectFill;
CALayer * containerLayer = self.imageView.layer.sublayers[0];
if (containerLayer != nil)
{
[containerLayer setValue:newImgView.layer forKey:#"__imageLayer"];
CALayer * holderLayer = [containerLayer valueForKey:#"__holderLayer"];
if (holderLayer != nil)
{
//!!!!!line below doesn't work!!!
//[holderLayer addSublayer:newImgView.layer];
//line below works!
[self.imageView.layer addSublayer:newImgView.layer];
}
}
[self.imageView setNeedsDisplay];
[self checkAndPrintLayers];
so the first nested layer is containerLayer, then holderLayer, and I'm expecting to add various images as sublayers to the holderLayer and then manipulate it. However, calling
[holderLayer addSublayer:newImgView.layer];
doesn't work; the imageView stays blank. However, calling
[self.imageView.layer addSublayer:newImgView.layer];
and adding a sublayer to the top layer works just dandy.
Am I missing something obvious here? Would love any suggestions.
thanks.
Because
holderLayer and containerLayer are transparent (holderLayer.opacity = 0 / containerLayer.opacity = 0),
Make it,
//container layer - the very top layer
CALayer *containerLayer = [CALayer layer];
containerLayer.opacity = 1.0;
containerLayer.bounds = [self.imageView.layer frame];
// Holder Layer
CALayer *holderLayer = [CALayer layer];
holderLayer.opacity = 1.0;
holderLayer.bounds = self.imageView.bounds;
Related
I am working on an ios application and i have a issue using CALayer it has created a transparent mask on every image i put in the Layer.
Please have a look at the code below :
self.mask = [CALayer layer];
self.mask.contents = CFBridgingRelease(([UIImage imageNamed:#"launch screen.png"].CGImage));
self.mask.bounds = CGRectMake(0, 0, 200, 200);
self.mask.anchorPoint = CGPointMake(0.5, 0.5);
self.mask.position = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
self.imageView = _imageView;
self.view.layer.mask = self.mask;
Please Refer to this image for example :
http://31.media.tumblr.com/10cc0ba92377a2cba9fb35c9943fd2ca/tumblr_inline_n6zpokNxpC1qh9cw7.gif
How to drop a shadow on UIImageView which has a masked image?
I don't mean a rectangular shadow - I'd like to apply the same mask effect to shadow too.
To give the Shadow Effect to UIImageView Try below code..
1) #import <QuartzCore/QuartzCore.h> in .h file
2) To give a shadow effect to Cell's UIImageView
mediaImage.layer.shadowColor = [UIColor blackColor].CGColor;
mediaImage.layer.shadowRadius = 10.f;
mediaImage.layer.shadowOffset = CGSizeMake(0.f, 5.f);
mediaImage.layer.shadowOpacity = 1.f;
mediaImage.clipsToBounds = NO;
Well! You can try this one.
// Use a White background to make the shadow prominent.
self.view.backgroundColor = [UIColor whiteColor];
// The image we're going to mask and shadow
UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"yourImage.jpeg"]];
image.center = self.view.center;
// Make new layer to contain shadow and masked image
CALayer *containerLayer = [CALayer layer];
containerLayer.shadowColor = [UIColor blackColor].CGColor;
containerLayer.shadowRadius = 10.f;
containerLayer.shadowOffset = CGSizeMake(0.f, 5.f);
containerLayer.shadowOpacity = 1.f;
// Use the image's layer to mask the image into a circle
image.layer.cornerRadius = roundf(image.frame.size.width/2.0);
image.layer.masksToBounds = YES;
// Add masked image layer into container layer so that it's shadowed
[containerLayer addSublayer:image.layer];
// Add container including masked image and shadow into view
[self.view.layer addSublayer:containerLayer];
You can custom a subclass called NEWImageVIew inherit UIImageView.In NEWImageVIew you can make a property called realImageContainer,which you can set image to this property.
#interface NEWImageView : UIImageView
#property (nonatomic,strong) UIImageView *realImageContainer;
#end
#implementation NEWImageView
- (UIImageView *)realImageContainer {
if (!_realImageContainer) {
_realImageContainer = [UIImageView new];
[self addSubview:_realImageContainer];
[_realImageContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
}
return _realImageContainer;
}
#end
When you want to make the image masked and shadowed, you can set image in realImageContainer and set mask to realImageContainer layer,so you get the masked layer.
NEWImageView *newImgView = [[NEWImageView alloc] init];
newImgView.backgroundColor = [UIColor clearColor];
newImgView.contentMode = UIViewContentModeScaleAspectFit;
newImgView.realImageContainer.image = self.image;
newImgView.realImageContainer.layer.mask = self.maskLayer;//this masklayer you can make youself
What about shadow?Because the realImageContainer is added to NEWImageView's view,the NEWImageView's layer not used yet,you can set shadow here.
newImgView.layer.shadowColor = [UIColor blackColor].CGColor;
newImgView.layer.shadowOpacity = 0.33;
newImgView.layer.shadowRadius = 8;
newImgView.layer.shadowOffset = CGSizeMake(0, 19);
so you get a masked and shadowed image.(I use a triangle image as mask,so I get this image)
you have to set an image with a transparent background and then you add the shadow like that:
imageView.layer.shadowColor = [UIColor blackColor].CGColor;
imageView.layer.shadowOpacity = 0.1;
imageView.layer.shadowRadius = 5;
imageView.layer.shadowOffset = CGSizeMake(5, 5);
[imageView setClipsToBounds:NO];
remember you have to import QuarzCore library
I am trying to use CALayer to display an image, but the image is not showing up. I've verified that 'image' is not nil, image.size is correct, and layer.contents is a valid CABackingStore.
- (void)viewDidLoad
{
[super viewDidLoad];
layer = [[CALayer alloc] init];
[self.view.layer addSublayer:layer];
UIImage *image = [UIImage imageNamed:#"download.jpeg"];
layer.bounds = CGRectMake(0, 0, image.size.width, image.size.height);
layer.position = self.view.center;
layer.contents = (id)image.CGImage;
[layer setNeedsDisplay];
}
What could be the problem here?
Removing [layer setNeedsDisplay]; should correct the behavior.
From the docs (emphasis added):
Calling this method causes the layer to recache its content. This results in the layer potentially calling either the displayLayer: or drawLayer:inContext: method of its delegate. The existing content in the layer’s contents property is removed to make way for the new content.
either use this
layer = [[CALayer alloc] init];
[self.view.layer addSublayer:layer];
//UIImage *image = [UIImage imageNamed:#"download.jpeg"];
layer.bounds = CGRectMake(0, 0, 300,300);
layer.position = self.view.center;
//layer.contents = (id)image.CGImage;
layer.contents = (id)[UIImage imageNamed:#"download.jpeg"].CGImage;
[layer setNeedsDisplay];
or
remove [layer setNeedsDisplay];
I guess the setNeedsDisplay made the layer to redraw the content and so deleting the image.
--
I am using MKNetwrkKit. I have an imageView, I have added it as a subView to a UIView. I download an image using "UIImageView+MKNetworkKitAdditions.h". I add a mask to the ImageView and remove it from superView, before the download is completed, and I get a crash!
- (void) testUIImageViewDownloadCrash {
UIImageView *imageView = [[UIImageView alloc] init];
[imageView mk_setImageAtURL:[NSURL URLWithString:#"http://www.gravatar.com/avatar/a717291747c76567bb0f086e15ae6e43?s=32&d=identicon&r=PG"] onCompletion:^(BOOL success, BOOL fromCache) {
//
}];
UIView *view = [[UIView alloc] init];
[view addSubview:imageView];
[self addMaskToImageView:imageView];
[imageView removeFromSuperview];
}
Now, the weird thing is, this crash occurs only when I add the mask... here is the function that adds the mask.
- (CAGradientLayer*) addMaskToImageView:(UIImageView *) inImageView
{
CALayer *imageLayer = inImageView.layer;
CGRect imageBounds = imageLayer.bounds;
CGRect ellipseRect = CGRectInset(imageBounds, 4, 4);
CGPathRef maskPath = CGPathCreateWithEllipseInRect(ellipseRect, NULL);
if (maskPath)
{
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.bounds = imageBounds;
maskLayer.position = (CGPoint){CGRectGetMidX(imageBounds), CGRectGetMidY(imageBounds)};
maskLayer.path = maskPath;
maskLayer.fillColor = [UIColor blackColor].CGColor;
imageLayer.mask = maskLayer;
CFRelease(maskPath);
}
CAGradientLayer *gradientRingLayer = [self createGradientRing:imageBounds];
CALayer *containerLayer = [CALayer layer];
[imageLayer.superlayer addSublayer:containerLayer];
// Move container layer to the image position
containerLayer.position = imageLayer.position;
// Image is now at 0,0 in the container
imageLayer.position = CGPointZero;
[containerLayer addSublayer:gradientRingLayer];
[containerLayer addSublayer:imageLayer];
layer.shouldRasterize = YES;
layer.rasterizationScale = [[UIScreen mainScreen] scale];
layer.contentsScale = [[UIScreen mainScreen] scale];
containerLayer.shadowColor = [UIColor blackColor].CGColor;
containerLayer.shadowOpacity = 1.0f;
containerLayer.shadowOffset = CGSizeMake(2.0f, 5.0f);
containerLayer.shadowRadius = 7.5f;
// Create shadow at the righ place around the image
CGPathRef containerShadowPath = CGPathCreateWithEllipseInRect(imageLayer.frame, NULL);
containerLayer.shadowPath = containerShadowPath;
CFRelease(containerShadowPath);
return gradientRingLayer;
}
- (CAGradientLayer*)createGradientRing:(CGRect)inBounds {
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.anchorPoint = CGPointMake(0.5f, 0.5f);
gradient.position = CGPointMake(0.0f, 0.0f);
// gradient.startPoint = CGPointMake(0.0,0.0);
// gradient.endPoint = CGPointMake(0.0,0.0);
gradient.bounds = inBounds;
gradient.cornerRadius = 0.0;
gradient.colors = [NSArray arrayWithObjects:
(id)[UIColor ringLight].CGColor,
(id)[UIColor ringLight].CGColor,
nil];
CAShapeLayer *frameLayer = [CAShapeLayer layer];
CGPathRef framePath = CGPathCreateWithEllipseInRect(CGRectInset(inBounds, 0, 0), NULL);
if (framePath)
{
frameLayer.bounds = inBounds;
frameLayer.position = (CGPoint){CGRectGetMidX(inBounds), CGRectGetMidY(inBounds)};
frameLayer.path = framePath;
frameLayer.fillColor = [UIColor blackColor].CGColor;
CFRelease(framePath);
}
gradient.mask = frameLayer;
return gradient;
}
If I comment out adding the mask, it won't crash. Another thing that I don't understand is, after adding the mask, if do this:
NSLog(#"subviews count : %i",[view.subviews count]);
then I get 0! Where did the imageView go?
I observed that the addMask function is making a superView of the imageView null. I found out that the line [containerLayer addSublayer:imageLayer]; is the culprit. This is making the superView of the imageView null. But why? And how can I fix it?
Sometimes I get this exception too, and I don't know why.
-[__NSCFString sublayers]: unrecognized selector sent to instance
I tried on iOS 5 and iOS 6.
Hai all am using CALayer to mask the UIImage, when i add the layer on imageview it display only layer portion hides remanning all image with white color filled
CALayer *mask = [CALayer layer];
mask.contents = (id)[[UIImage imageNamed:#"mask.png"] CGImage];
mask.frame = CGRectMake(0, 0, mainImageWidth+30, mainImageHeight);
mask.shadowOffset = CGSizeMake(0, 3);
mask.shadowOpacity = 1.5;
mainImageView.layer.mask = mask;
[mainImageView.layer setMasksToBounds:NO];
it hides my image view except the layer portion. how do i solve this
Instead of create mask using image view i have added three mask for UIView now its working perfect
mainLayer.frame = CGRectMake(0, 0, mainImageWidth, mainImageHeight);
[self.view.layer addSublayer:mainLayer];
mainLayer.backgroundColor = [UIColor clearColor].CGColor;
secondLayer.frame = CGRectMake(gloss_x, gloss_y, gloss_w, gloss_h);
maskLayer = [CALayer layer];
UIImage *mask = [UIImage imageNamed:#"mask.png"];
maskLayer.contents = (id)mask.CGImage;
maskLayer.frame = maskRect;//CGRectMake(gloss_x, gloss_y-50, gloss_w, gloss_h);
secondLayer.contents = (id)s_glossImage.CGImage;
[mainLayer addSublayer:secondLayer];
mainLayer.mask = maskLayer;
[mainImageView.layer addSublayer:mainLayer];
Now its working fine.