2012-07-13 12 views
17

Estoy intentando animar la transición de un CALayer de esquinas normales a esquinas redondeadas. Solo quiero redondear las esquinas superiores, entonces estoy usando un UIBezierPath. Aquí está el código:CALa animación básica con la ruta CALayer no anima

UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight; 

UIBezierPath* newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(8.0f, 8.0f)]; 
UIBezierPath* oldPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(0.0f, 0.0f)]; 

CAShapeLayer* layer = [CAShapeLayer layer]; 
layer.frame = self.bounds; 
layer.path = oldPath.CGPath; 

self.layer.mask = layer; 

CABasicAnimation* a = [CABasicAnimation animationWithKeyPath:@"path"]; 
[a setDuration:0.4f]; 
[a setFromValue:(id)layer.path]; 
[a setToValue:(id)newPath.CGPath]; 

layer.path = newPath.CGPath; 
[layer addAnimation:a forKey:@"path"]; 

Pero cuando corro esto, las esquinas están redondeadas, pero no hay animación- que sucede al instante. He visto algunas preguntas similares aquí en SO, pero no resolvieron mi problema.

iPhone CALayer animation

Animating CALayer's shadowPath property

Estoy seguro de que estoy haciendo una pequeña cosa equivocada que está causando el problema, pero para la vida de mí no puedo entenderlo.

Solución:

- (void)roundCornersAnimated:(BOOL)animated { 
    UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight; 

    UIBezierPath* newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(8.0f, 8.0f)]; 
    UIBezierPath* oldPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(0.0001f, 0.0001f)]; 

    CAShapeLayer* layer = [CAShapeLayer layer]; 
    layer.frame = self.bounds; 

    self.layer.mask = layer; 

    if(animated) { 
     CABasicAnimation* a = [CABasicAnimation animationWithKeyPath:@"path"]; 
     [a setDuration:0.4f]; 
     [a setFromValue:(id)oldPath.CGPath]; 
     [a setToValue:(id)newPath.CGPath]; 

     layer.path = newPath.CGPath; 
     [layer addAnimation:a forKey:@"path"]; 
    } else { 
     layer.path = newPath.CGPath; 
    } 
} 

Realmente todo lo que tenía que hacer con una fijación adecuada 'del' valor para la animación.

+1

solución sería bueno como una respuesta en lugar de parte de la pregunta, pero esto es muy útil de todos modos así – buildsucceeded

Respuesta

10

Me parece que está creando una capa de forma que no tiene una ruta, y luego trata de animarla para agregarle una ruta. Las capas de forma son casos especiales, y no funcionan de esa manera.

Debe tener una ruta en la capa de forma antes y después de la animación, y la ruta debe tener el mismo número de puntos tanto antes como después.

Debería crear una ruta de rectángulo redondeada con un radio de esquina de 0 (manualmente, utilizando una serie de arcos de esquina y lados) y luego crear una nueva ruta con radios distintos para las esquinas que desea redondear y instala esa ruta como tu animación.

Incluso eso podría no funcionar, porque la ruta necesita tener exactamente el mismo número de puntos en ella, y sospecho que los arcos se simplificarían a puntos cuando el radio es cero.

Acabo de encontrar una llamada UIBezierPath que creará un rectángulo donde puede seleccionar qué esquinas redondear. La llamada es bezierPathWithRoundedRect: byRoundingCorners: cornerRadii:

Eso creará un rectángulo con tantas esquinas redondeadas como desee. Sin embargo, no estoy seguro de si funcionará para la animación de ruta. Es posible que deba solicitar redondear todas las esquinas con las 2 esquinas no redondeadas ajustadas a radio cero. De esta forma, PODRÍA obtener una ruta con la misma cantidad de puntos que una ruta de rectángulo redondeada para que la animación de ruta funcione correctamente. Tendrás que intentarlo.

+0

1 :) Gracias. Usted tenía razón. Establecer un valor 'de' correcto para la animación lo hizo. –

4

tratar de poner:

layer.path = newPath.CGPath; 

después:

[layer addAnimation:a forKey:@"path"]; 
Cuestiones relacionadas