I am trying to tap one of five circles and start an animation that will gradually change the selected background to the same colour as the tapped circle. I’ve managed to get UITapGestureRecognizer to respond to a tap gesture on any one of five circles but I can’t work out how to find out how to identify each circle.
The UIKit Framework Reference documentation on UIGestureRecognizer says
A gesture recognizer operates on touches hit-tested to a specific view
and all of that view’s subviews
and that
Clients of gesture recognisers can also ask for the location of a
gesture by calling locationInView: or locationOfTouch:inView”.
This made me think the tapped circles probably need to be made into images.
But is this really what I need to do ?
Here’s the code so far
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];
[self.view setUserInteractionEnabled:YES];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(method:)];
tap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tap];
CAShapeLayer *circleLayer1 = [CAShapeLayer layer];
[circleLayer1 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(75.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer1 setStrokeColor:[[UIColor cyanColor] CGColor]];
[circleLayer1 setFillColor:[[UIColor cyanColor] CGColor]];
[[self.view layer] addSublayer:circleLayer1];
CAShapeLayer *circleLayer2 = [CAShapeLayer layer];
[circleLayer2 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(125.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer2 setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer2 setFillColor:[[UIColor redColor] CGColor]];
[[self.view layer] addSublayer:circleLayer2];
CAShapeLayer *circleLayer3 = [CAShapeLayer layer];
[circleLayer3 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(175.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer3 setStrokeColor:[[UIColor yellowColor] CGColor]];
[circleLayer3 setFillColor:[[UIColor yellowColor] CGColor]];
[[self.view layer] addSublayer:circleLayer3];
CAShapeLayer *circleLayer4 = [CAShapeLayer layer];
[circleLayer4 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(225.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer4 setStrokeColor:[[UIColor magentaColor] CGColor]];
[circleLayer4 setFillColor:[[UIColor magentaColor] CGColor]];
[[self.view layer] addSublayer:circleLayer4];
CAShapeLayer *circleLayer5 = [CAShapeLayer layer];
[circleLayer5 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(275.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer5 setStrokeColor:[[UIColor greenColor] CGColor]];
[circleLayer5 setFillColor:[[UIColor greenColor] CGColor]];
[[self.view layer] addSublayer:circleLayer5];
}
- (void)method:(id)sender {
[UIView animateWithDuration:3.0 animations:^{
self.view.layer.backgroundColor = [UIColor cyanColor].CGColor;
} completion:NULL];
}
To show what I’m trying to do, I’ve set up the method so it changes the background layer to the colour of the circle on the left.
But what do I need to do [a] to identify which circle was tapped and [b] represent the tapped spots as circles that would also gradually change colour so the whole screen changes to the colour of the circle that was tapped ?
I suggest you to remove the UITapGestureRecognizer that you added to the whole view.
Then add a name to each CAShapeLayer so you can distinguish between them :
self.view.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];
[self.view setUserInteractionEnabled:YES];
CAShapeLayer *circleLayer1 = [CAShapeLayer layer];
[circleLayer1 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(75.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer1 setStrokeColor:[[UIColor cyanColor] CGColor]];
[circleLayer1 setFillColor:[[UIColor cyanColor] CGColor]];
[circleLayer1 setName:#"circleLayer1"];
[[self.view layer] addSublayer:circleLayer1];
CAShapeLayer *circleLayer2 = [CAShapeLayer layer];
[circleLayer2 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(125.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer2 setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer2 setFillColor:[[UIColor redColor] CGColor]];
[circleLayer2 setName:#"circleLayer2"];
[[self.view layer] addSublayer:circleLayer2];
CAShapeLayer *circleLayer3 = [CAShapeLayer layer];
[circleLayer3 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(175.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer3 setStrokeColor:[[UIColor yellowColor] CGColor]];
[circleLayer3 setFillColor:[[UIColor yellowColor] CGColor]];
[circleLayer3 setName:#"circleLayer3"];
[[self.view layer] addSublayer:circleLayer3];
CAShapeLayer *circleLayer4 = [CAShapeLayer layer];
[circleLayer4 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(225.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer4 setStrokeColor:[[UIColor magentaColor] CGColor]];
[circleLayer4 setFillColor:[[UIColor magentaColor] CGColor]];
[circleLayer4 setName:#"circleLayer4"];
[[self.view layer] addSublayer:circleLayer4];
CAShapeLayer *circleLayer5 = [CAShapeLayer layer];
[circleLayer5 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(275.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer5 setStrokeColor:[[UIColor greenColor] CGColor]];
[circleLayer5 setFillColor:[[UIColor greenColor] CGColor]];
[circleLayer5 setName:#"circleLayer5"];
[[self.view layer] addSublayer:circleLayer5];
Then you can add this method that allows you to detect wich CAShapeLayer has been touched:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:self.view];
for (id sublayer in self.view.layer.sublayers) {
if ([sublayer isKindOfClass:[CAShapeLayer class]]) {
CAShapeLayer *shapeLayer = sublayer;
if (CGPathContainsPoint(shapeLayer.path, 0, touchLocation, YES)) {
NSLog(#"Layer's name is: %#",shapeLayer.name);
}
}
}
}
}
Now that you can detect which CAShapeLayer has been touched, you can customize the color of your view as you prefer
There is a method called locationInView:(UIView *)view that will help you to find the location. You know the rects of all the circles and check whether the location is inside of any rect using the method CGRectContainsPoint(CGRect rect, CGPoint point) If its inside you can check whether the selected location is radius distance from the centre. Hope this will solve your issue.
For Q.(b) I attached a sample you can refer it,
UIColor *stroke = rippleColor ? rippleColor : [UIColor colorWithWhite:0.8 alpha:0.8];
CGRect pathFrame = CGRectMake(-CGRectGetMidX(self.bounds), -CGRectGetMidY(self.bounds), self.bounds.size.width, self.bounds.size.height);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:pathFrame cornerRadius:self.layer.cornerRadius];
// accounts for left/right offset and contentOffset of scroll view
CGPoint shapePosition = [self convertPoint:self.center fromView:nil];
CAShapeLayer *circleShape = [CAShapeLayer layer];
circleShape.path = path.CGPath;
circleShape.position = shapePosition;
circleShape.fillColor = [UIColor clearColor].CGColor;
circleShape.opacity = 0;
circleShape.strokeColor = stroke.CGColor;
circleShape.lineWidth = 3;
[self.layer addSublayer:circleShape];
[CATransaction begin];
//remove layer after animation completed
[CATransaction setCompletionBlock:^{
[circleShape removeFromSuperlayer];
}];
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2.5, 2.5, 1)];
CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
alphaAnimation.fromValue = #1;
alphaAnimation.toValue = #0;
CAAnimationGroup *animation = [CAAnimationGroup animation];
animation.animations = #[scaleAnimation, alphaAnimation];
animation.duration = 0.5f;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[circleShape addAnimation:animation forKey:nil];
[CATransaction commit];
}
[UIView animateWithDuration:0.1 animations:^{
imageView.alpha = 0.4;
self.layer.borderColor = [UIColor colorWithWhite:1 alpha:0.9].CGColor;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.2 animations:^{
imageView.alpha = 1;
self.layer.borderColor = [UIColor colorWithWhite:0.8 alpha:0.9].CGColor;
}completion:^(BOOL finished) {
if([superSender respondsToSelector:methodName]){
[superSender performSelectorOnMainThread:methodName withObject:nil waitUntilDone:NO];
}
if(_block) {
BOOL success= YES;
_block(success);
}
}];
}];
}`
As pointed by the others answers you have some options, but I think that the easiest, is to check in your method what layer you tapped.
You just need to change your method to something like that:
- (void)method:(UITapGestureRecognizer *)gesture {
CGPoint touchLocation = [gesture locationInView:self.view];
for (id sublayer in self.view.layer.sublayers) {
if ([sublayer isKindOfClass:[CAShapeLayer class]]) {
CAShapeLayer *shapeLayer = sublayer;
if (CGPathContainsPoint(shapeLayer.path, 0, touchLocation, YES)) {
[UIView animateWithDuration:3.0 animations:^{
shapeLayer.strokeColor = [UIColor blackColor].CGColor;
shapeLayer.fillColor = [UIColor blackColor].CGColor;
} completion:NULL];
}
}
}
}
You don't need to add any UITapGestureRecognizer to your view, you just need to add names to your layers and implement the following method:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:self.view];
for (id sublayer in self.view.layer.sublayers) {
if ([sublayer isKindOfClass:[CAShapeLayer class]]) {
CAShapeLayer *shapeLayer = sublayer;
if (CGPathContainsPoint(shapeLayer.path, 0, touchLocation, YES)) {
// This touch is in this shape layer
NSLog(#"Name of layer is: %#",shapeLayer.name);
}
} else {
CALayer *layer = sublayer;
if (CGRectContainsPoint(layer.frame, touchLocation)) {
// Touch is in this rectangular layer
}
}
}
}
}
After identifing your layer you can change the color of layer accordingly.
Or if you have limited layers than you can identify it as follows for your no of layers:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:self.view];
if (CGPathContainsPoint(shape1.path, 0, touchLocation, YES)) {
// This touch is in this shape layer
NSLog(#"Name of layer 1 is: %#",shape1.name);
}
if (CGPathContainsPoint(shape2.path, 0, touchLocation, YES)) {
// This touch is in this shape layer
NSLog(#"Name of layer 2 is: %#",shape2.name);
}
if (CGPathContainsPoint(shape3.path, 0, touchLocation, YES)) {
// This touch is in this shape layer
NSLog(#"Name of layer 3 is: %#",shape3.name);
}
if (CGPathContainsPoint(shape4.path, 0, touchLocation, YES)) {
// This touch is in this shape layer
NSLog(#"Name of layer 4 is: %#",shape4.name);
}
if (CGPathContainsPoint(shape5.path, 0, touchLocation, YES)) {
// This touch is in this shape layer
NSLog(#"Name of layer 5 is: %#",shape5.name);
}
}
}
Related
I have one UIView with size 141 X 161. Then I created a circle .Here is that code:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 86, 79)] CGPath]];
[[self.photoView layer] addSublayer:circleLayer];
[circleLayer setStrokeColor:[[UIColor blackColor] CGColor]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
}
photoview is my uiview
When I run it's not in centre,
I need my circle in perfect centre of inside my UIView ( 141 x 161). And also need to set outside border.
And my circle is think.how to set radius at 1.
And my circle fill should be #222222
Border: thickness = 1.9
color = white
position = centre
I am new to iOS.
Try this :
CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(27, 41, 86, 79)] CGPath]];
[[self.photoView layer] addSublayer:circleLayer];
[circleLayer setStrokeColor:[[UIColor whiteColor] CGColor]];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
circleLayer.lineWidth = 0.5;
circleLayer.shadowColor = [UIColor whiteColor].CGColor;
circleLayer.shadowOpacity = 0.4;
circleLayer.borderColor = [UIColor whiteColor] .CGColor;
circleLayer.borderWidth = 2;
circleLayer.fillColor =[UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.25].CGColor;
circleLayer.borderColor = [[UIColor whiteColor] CGColor];
I want to draw a circle in iOS. It can be an image view or view, I want to adjust its size on gestures. Like, dragging from outside to the center, the radius of the circle should reduce and so vice versa.
Please note that I want to fix the position of that view, circle or image. I just want to adjust the size as it is dragged.
try this
- (IBAction)pinch:(UIPinchGestureRecognizer *)sender {
double scale=[sender scale];
self.view1.frame=CGRectMake(self.view1.frame.origin.x*scale, self.view1.frame.origin.y*scale, self.view1.frame.size.width*scale, self.view1.frame.size.height*scale);
[self.view1.layer setCornerRadius:5];
}
Try this.
- (IBAction)pan:(UIPanGestureRecognizer *)sender {
for (CALayer *layer in self.imageView.layer.sublayers) {
[layer removeFromSuperlayer];
}
CGPoint scale =[sender locationInView:sender.view];
CAShapeLayer *circleLayer = [CAShapeLayer layer];
[circleLayer setBounds:CGRectMake(0.0f, 0.0f, [_imageView bounds].size.width,
[_imageView bounds].size.height)];
[circleLayer setPosition:CGPointMake(CGRectGetMidX([_imageView bounds]),CGRectGetMidY([_imageView bounds]))];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, CGRectGetWidth(_imageView.frame)+scale.x, CGRectGetHeight(_imageView.frame)+scale.y)];
[circleLayer setPath:[path CGPath]];
[circleLayer setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer setLineWidth:1.0f];
[circleLayer setFillColor:[[UIColor clearColor] CGColor]];
[[_imageView layer] addSublayer:circleLayer];
}
I am trying to draw a CAShapeLayer in a UIView and update the strokeStart and strokeEnd in response to a changing variable. The shape layer is created and drawn on screen as it should, but I am not able to update it.
My code:
//drawing shapeLayer on screen
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
shapeLayer = [CAShapeLayer layer];
UIBezierPath *variometerGuage = [UIBezierPath bezierPath];
[variometerGuage moveToPoint:CGPointMake(25, 5)];
[variometerGuage addLineToPoint:CGPointMake(25, 200)];
[shapeLayer setPath:variometerGuage.CGPath];
shapeLayer.strokeStart = 0;
shapeLayer.strokeEnd = .5;
shapeLayer.strokeColor = [UIColor colorWithWhite:0.5 alpha:1.0].CGColor;
shapeLayer.lineWidth = 10;
[shapeLayer setLineCap:kCALineCapButt];
[self.layer addSublayer:shapeLayer];
}
The following code is called from the View Controller. I know it is being executed, but the UIView is not updated.
- (void)updateVariometerGraphocsWithLift:(float)vario {
shapeLayer.strokeStart = vario; //vario being a number between 0 and 1
[shapeLayer setNeedsDisplay];
[self.layer addSublayer:shapeLayer];
[self.layer setNeedsDisplay];
[self.layer setNeedsLayout];
}
Any ideas?
In a UIView subclass, I have this method:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * aTouch = [touches anyObject];
CGPoint loc = [aTouch locationInView:self];
CALayer * layer = [CALayer layer];
[layer setBackgroundColor: [[UIColor colorWithHue:(float)rand()/RAND_MAX saturation:1 brightness:1 alpha:1] CGColor]];
[layer setFrame:CGRectMake(0, 0, 64, 64)];
[layer setCornerRadius:7];
[layer setPosition:loc];
[layer setOpacity:0];
[self.layer addSublayer:layer];
CABasicAnimation * opacityAnim = [CABasicAnimation animationWithKeyPath:#"opacity"];
opacityAnim.duration=2.42;
opacityAnim.fromValue=[NSNumber numberWithFloat:0];
opacityAnim.toValue= [NSNumber numberWithFloat:1];
opacityAnim.fillMode = kCAFillModeForwards;
opacityAnim.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
opacityAnim.removedOnCompletion=NO;
opacityAnim.delegate=self;
// explicit animation is working as expected
// [layer addAnimation:opacityAnim forKey:#"opacityAnimation"];
// Why isn't the implicit animation working ?
[layer setOpacity:1];
}
What am I missing ? I expect the CALayer layer's opacity to be implicitly animated with the last line in this method.
My solution
Here is how I solved the problem thanks to Duncan's answer.
-(CALayer *) layerFactory:(CGPoint) loc {
CALayer * layer = [CALayer layer];
[layer setBackgroundColor: [[UIColor colorWithHue:(float)rand()/RAND_MAX saturation:1 brightness:1 alpha:1] CGColor]];
[layer setFrame:CGRectMake(0, 0, 64, 64)];
[layer setCornerRadius:7];
[layer setPosition:loc];
[layer setOpacity:0];
return layer;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * aTouch = [touches anyObject];
CGPoint loc = [aTouch locationInView:self];
[CATransaction begin];
CALayer * layer = [self layerFactory:loc];
[self.layer addSublayer:layer];
[CATransaction commit];
[CATransaction begin];
[CATransaction setAnimationDuration:0.45];
[layer setOpacity:1];
[CATransaction commit];
}
You only need to put the creation of the layer, and the modifiction of the opacity in two different CATransaction blocks. However, moving the creation (not the adding) of the layer to the layerFactory method changes nothing to the situation.
I don't know whether it's the best solution, but it's working.
You can't create a layer and set it's opacity, then set the opacity to a new value in the same method and get implicit animation. Try putting your create/configure layer code inside a CATransaction begin/end block, and then the code to set the opacity to 1 inside another transaction begin/end block.
I think that will work, but would have to try it to be sure.
If that doesn't work, invoke the code to set the opacity to 1 using performSelector:withObject:afterDelay and a delay value of 0. That will let the system add your layer with an opacity of 0, then treat the change of opacity to 1 as a separate transaction.
I am trying to animate the width of a rounded rectangle, the problem is when going from bigger width to thinner width, the animation does an "aberration ease jump".
Here's the code:
shapeLayer = [CAShapeLayer layer];
shapeRect = CGRectMake(0.0f, 0.0f, 150.0f, 200.0f);
[shapeLayer setBounds:shapeRect];
[shapeLayer setPosition:CGPointMake(iniPosX, 80.0f)];
[shapeLayer setFillColor:[[UIColor blackColor] CGColor]];
[shapeLayer setStrokeColor:[[UIColor clearColor] CGColor]];
[shapeLayer setLineWidth:1.0f];
[shapeLayer setLineJoin:kCALineJoinRound];
[shapeLayer setOpacity:0.2];
path = [UIBezierPath bezierPathWithRoundedRect:shapeRect cornerRadius:15.0];
[shapeLayer setPath:path.CGPath];
[self.layer addSublayer:shapeLayer];
And when I start the animation:
- (void)adjustSelectorToPosAndSize:(float)posX andWidth:(float)width
{
shapeRect = CGRectMake(0.0f, 0.0f, width, 200.0f);
[shapeLayer setBounds:shapeRect];
[shapeLayer setPosition:CGPointMake(posX, 80.0f)];
path = [UIBezierPath bezierPathWithRoundedRect:shapeRect cornerRadius:15.0];
[shapeLayer setPath:path.CGPath];
}
What am I doing wrong?
Doing this with a CAShapeLayer seems overly complicated to me if you are only using it for a rounded rectangle. Why not simply use a CALayer with the cornerRadius properly set?
Animating the frame with cornerRadius set will work fine.
myLayer = [CALayer layer];
shapeRect = CGRectMake(0.0f, 0.0f, 150.0f, 200.0f);
[myLayer setBounds:shapeRect];
[myLayer setPosition:CGPointMake(iniPosX, 80.0f)];
[myLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
[myLayer setBorderColor:[[UIColor clearColor] CGColor]];
[myLayer setBorderWidth:1.0f];
[myLayer setOpacity:0.2];
[myLayer setCornerRadius:15.0];
[self.layer addSublayer:myLayer];
Animating it is done by simply chaining the frame (not the path)
- (void)adjustSelectorToPosAndSize:(float)posX andWidth:(float)width
{
shapeRect = CGRectMake(0.0f, 0.0f, width, 200.0f);
[myLayer setBounds:shapeRect];
[myLayer setPosition:CGPointMake(posX, 80.0f)];
}
Important:
Some of the properties changed name like fillColor became backgroundColor and the strokeColor and lineWidth became borderColor and borderWidth etc.
Although CAShapeLayer’s path property is animatable, it does not do so implicitly like bounds and position, you have to make an explicit animation:
CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath: #"path"];
anim.fromValue = (id) fromPath.CGPath;
anim.toValue = (id) toPath.CGPath;
anim.duration = 1.0;
[layer addAnimation: anim forKey: #“resize”];
Since you probably want all three animations to happen together, you can make them all explicit and grouped together:
CABasicAnimation* anim1 = [CABasicAnimation animationWithKeyPath: #"position"];
anim1.fromValue = [NSValue valueWithCGPoint: fromPosition];
anim1.toValue = [NSValue valueWithCGPoint: toPosition];
anim1.duration = 1.0;
CABasicAnimation* anim2 = [CABasicAnimation animationWithKeyPath: #"bounds"];
anim2.fromValue = [NSValue valueWithCGRect: fromBounds];
anim2.toValue = [NSValue valueWithCGRect: toBounds];
anim2.duration = 1.0;
CABasicAnimation* anim3 = [CABasicAnimation animationWithKeyPath: #"path"];
anim3.fromValue = (id) fromPath.CGPath;
anim3.toValue = (id) toPath.CGPath;
anim3.duration = 1.0;
CAAnimationGroup* animG = [CAAnimationGroup animation];
animG.animations = [NSArray arrayWithObjects: anim1, anim2, anim3, nil];
animG.duration = 1.0;
[layer addAnimation: animG forKey:#"resize"];
If your shape does not have contents or children then you may be able to use a CALayer instead:
CALayer* rectLayer = [CALayer layer];
rectLayer.masksToBounds = YES;
rectLayer.bounds = startBounds;
rectLayer.backgroundColor = [[UIColor blackColor] CGColor];
rectLayer.cornerRadius = 15.0;
[self.layer addSublayer: rectLayer];
// Then later implicitly animate the bounds:
rectLayer.bounds = newBounds;