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.
--
Related
In the code, I have set:
imageView.layer.masksToBounds = YES;
imageView.layer.cornerRadius = imageView.frame.size.width/2;
And run it in animation block:
[UIView transitionWithView:imageView
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:nil
completion:^(BOOL finished) {
imageView.hidden = YES;
}];
But when running on iOS 8, the imageView is back to normal, means there is no cornerRadius for imageView.
Could anyone tell me why?
You need to slash corners of UIImage not UIImageView using CALayer using below code.
// load image on imageView programmatically
UIImage *image = [UIImage imageNamed:#"yourImage.png"];
// assign the changes reflected using method before load image to imageView
image = [self makeRoundedImage:image radius:_imageView.frame.size.width/2];
_imageView.image = image;
// method to create round image
-(UIImage *)makeRoundedImage:(UIImage *) image radius: (float) radius{
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = CGRectMake(0, 0, image.size.width, image.size.height);
imageLayer.contents = (id) image.CGImage;
imageLayer.masksToBounds = YES;
imageLayer.cornerRadius = radius;
UIGraphicsBeginImageContext(image.size);
[imageLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return roundedImage;
}
Now you can apply animation simply.
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;
In my application, I want to set the background image on UIView. In the simulator iOS this code works. And on the iPhone black background. Here's the code:
- (void)viewDidLoad
{
[super viewDidLoad];
UIGraphicsBeginImageContext(self.view.frame.size);
[[UIImage imageNamed:#"appBG.png"] drawInRect:self.view.bounds];
UIImage *appbg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.view.backgroundColor = [UIColor colorWithPatternImage:appbg];
}
UPDATE: I decided my problem
its better u will take an ImageView on UIView and set the image to it. Rather than setting the image to UIView.
Try this code:
UIImage* backgroundImage = [UIImage imageNamed:#"appBG.png"];
CALayer* aLayer = [CALayer layer];
CGFloat nativeWidth = CGImageGetWidth(backgroundImage.CGImage);
CGFloat nativeHeight = CGImageGetHeight(backgroundImage.CGImage);
CGRect startFrame = CGRectMake(0.0, 0.0, nativeWidth, nativeHeight);
aLayer.contents = (id)backgroundImage.CGImage;
aLayer.frame = startFrame;
[self.view.layer addSublayer:aLayer];
[aLayer setNeedsDisplay];
Adjust startFrame value according to your requirement.
Try with Replace following line:
[[UIImage imageNamed:#"appBG.png"] drawInRect:self.view.bounds];
With following line:
[[UIImage imageNamed:#"appBG.png"] drawInRect:self.view.frame];
May be the issue of frame or bound.
I'm trying to create a UIbutton that has the following characteristics:
* A custom image as its content
* Rounded corners
* A drop shadow
Using the following code will format the button to appear correctly and function but the highlight action (i.e., the darkening of the button when touched) is lost when the touch occurs. Any ideas?
+(void) styleButton:(UIButton*)button{
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(button.bounds.origin.x, button.bounds.origin.y, button.bounds.size.width, button.bounds.size.height)];
CALayer *sublayer = [CALayer layer];
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius = 5.0;
sublayer.shadowColor = [UIColor blackColor].CGColor;
sublayer.shadowOpacity = 0.8;
sublayer.frame = CGRectMake(button.bounds.origin.x, button.bounds.origin.y, button.bounds.size.width, button.bounds.size.height);
backgroundView.userInteractionEnabled = NO;
[backgroundView.layer addSublayer:sublayer];
[button insertSubview:backgroundView atIndex:0];
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = sublayer.bounds;
imageLayer.cornerRadius = 10.0;
imageLayer.contents = (id) [UIImage imageNamed:#"myImage.png"].CGImage;
imageLayer.cornerRadius = 5.0f;
imageLayer.masksToBounds = YES;
[sublayer addSublayer:imageLayer];
}
Have you tried converting your backgroundView into a UIImage and add it to the button instead of adding backgroundView as a subview? That would preserve the darkening when the button is pressed:
UIGraphicsBeginImageContext(backgroundView.frame.size);
[backgroundView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[button setImage:image forState:UIControlStateNormal];
Like this (ARC enabled):
UIGraphicsBeginImageContextWithOptions(self.button.bounds.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIView *aView in self.button.subviews) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, aView.frame.origin.x, aView.frame.origin.y);
[aView.layer renderInContext:UIGraphicsGetCurrentContext()];
CGContextRestoreGState(context);
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.button setImage:image forState:UIControlStateNormal];
[self.button.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
[self.button setAdjustsImageWhenHighlighted:YES];
What is the best way to move an image along an array of dots?
My recommended approach would be to wrap the UIImage in a UIImageView and use a CAKeyframeAnimation to animate your UIImageView's layer along a path that passes through your three points:
UIImage *image = [UIImage imageNamed:#"image.png"];
imageView = [[UIImageView alloc] initWithImage:image];
[mainView addSubview:imageView];
// Remember to remove the image view and release it when done with it
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.duration = 1.0f;
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
CGMutablePathRef pointPath = CGPathCreateMutable();
CGPathMoveToPoint(pointPath, NULL, viewOrigin.x, viewOrigin.y);
CGPathAddLineToPoint(pointPath, NULL, point1.x, point1.y);
CGPathAddLineToPoint(pointPath, NULL, point2.x, point2.y);
CGPathAddLineToPoint(pointPath, NULL, point3.x, point3.y);
pathAnimation.path = pointPath;
CGPathRelease(pointPath);
[imageView.layer addAnimation:pathAnimation forKey:#"pathAnimation"];
Note that by default, the position of a layer is at the layer's center. If you'd like to move the layer relative to another reference point, you can set the layer's anchorPoint property to something like (0.0, 0.0) for its upper-left corner (on the iPhone) or (0.0, 1.0) for its lower left.
Also, this won't change the frame of the UIImageView when it's done, so if you refer to that frame later on, you may need to either take that into account or add a delegate method callback for the end of your animation to set it to the proper value.
You can also make your image move along curves, instead of straight lines, by replacing the calls to CGPathAddLineToPoint() with CGPathAddCurveToPoint().
EDIT (5/14/2009): I added the missing pathAnimation.path = pointPath line and changed a mistyped reference to curvedPath to pointPath.
The easiest way is to uses UIView animations
A quick example that assumes you are able to use UIImageView to hold your image and NSArray to hold your point.
UIImage *image = [UIImage imageNamed:#"image.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[someView addSubview:imageView]; // Assume someView exists
NSValue *firstPoint = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
NSValue *secondPoint = [NSValue valueWithCGPoint:CGPointMake(100, 0)];
NSValue *thirdPoint = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
// And so on....
NSArray *points = [NSArray arrayWithObjects:firstPoint, secondPoint, thirdPoint, nil];
for (NSValue *pointValue in points) {
[UIView beginAnimations:#"UIImage Move" context:NULL];
CGPoint point = [pointValue CGPointValue];
CGSize size = imageView.frame.size;
imageView.frame = CGRectMake(point.x, point.y, size.width, size.height);
[UIView commitAnimations];
}