(iOS) ¿Cómo animar rectángulo networkingondeado con shapeLayer?

Estoy tratando de animar el ancho de un rectángulo networkingondeado, el problema es cuando se pasa de ancho mayor a ancho más delgado, la animation hace un "salto de facilidad de aberración".

Aquí está el código:

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]; 

Y cuando comienzo la 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]; } 

¿Qué estoy haciendo mal?

Hacer esto con un CAShapeLayer me parece demasiado complicado si solo lo estás utilizando para un rectángulo networkingondeado. ¿Por qué no simplemente utilizar un CALayer con el cornerRadius configurado correctamente ?

Animar el marco con el juego cornerRadius funcionará bien.

 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]; 

La animation se realiza simplemente encadenando el marco (no el 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)]; } 

Importante:

Algunas de las properties cambiaron el nombre como fillColor convirtió en backgroundColor y strokeColor y lineWidth convirtieron en borderColor y borderWidth etc.

Aunque la propiedad de ruta de CAShapeLayer es animable, no lo hace implícitamente, como los límites y la position, debe hacer una animation explícita:

 CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath: @"path"]; anim.fromValue = (id) fromPath.CGPath; anim.toValue = (id) toPath.CGPath; anim.duration = 1.0; [layer addAnimation: anim forKey: @“resize”]; 

Como es probable que desee que las tres animaciones se produzcan juntas, puede hacer que todas sean explícitas y agrupadas:

 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"]; 

Si su forma no tiene contenidos o niños, entonces puede usar un CALayer en su lugar:

 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;