2010-10-25 12 views
13

J'ai un CALayer personnalisé (disons CircleLayer), contenant des propriétés personnalisées (rayon et teinte). La couche se rend dans sa méthode drawInContext:Pourquoi l'animation de propriétés CALayer personnalisées entraîne-t-elle l'absence d'autres propriétés pendant l'animation?

- (void)drawInContext:(CGContextRef)ctx { 
    NSLog(@"Drawing layer, tint is %@, radius is %@", self.tint, self.radius); 

    CGPoint centerPoint = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2); 

    CGContextMoveToPoint(ctx, centerPoint.x, centerPoint.y); 
    CGContextAddArc(ctx, centerPoint.x, centerPoint.y, [self.radius doubleValue], radians(0), radians(360), 0); 
    CGContextClosePath(ctx); 

    /* Filling it */ 
    CGContextSetFillColorWithColor(ctx, self.tint.CGColor); 
    CGContextFillPath(ctx); 
} 

Je veux que le rayon soit animable donc j'ai mis

+ (BOOL)needsDisplayForKey:(NSString *)key { 
    if ([key isEqualToString:@"radius"]) { 
     return YES; 
    } 
    return [super needsDisplayForKey:key]; 
} 

Et l'animation est effectuée comme ceci:

CABasicAnimation *theAnimation=[CABasicAnimation animationWithKeyPath:@"radius"]; 
theAnimation.duration=2.0; 
theAnimation.fromValue=[NSNumber numberWithDouble:100.0]; 
theAnimation.toValue=[NSNumber numberWithDouble:50.0]; 
theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

[circleLayer addAnimation:theAnimation forKey:@"animateRadius"]; 

circleLayer.radius = [NSNumber numberWithDouble:50.0]; 

drawInContext: est appelé comme prévu lors de l'animation pour redessiner le cercle, cependant la teinte est nulle dès le début de l'animation et revient à sa valeur d'origine à la fin de l'animation.

Je suis arrivé à la conclusion que si je veux animer une propriété personnalisée et que d'autres propriétés doivent conserver leur valeur pendant l'animation, je dois les animer aussi, ce que je trouve peu pratique. Le but n'est pas de faire grandir/rétrécir un cercle, je sais que je peux utiliser la transformation pour cela. C'est seulement pour illustrer avec un exemple simple le problème de l'animation d'une seule propriété personnalisée sans avoir à animer toutes les autres.

J'ai fait un projet simple qui illustre la question que vous pouvez trouver ici: Sample project illustrating the issue

Il y a probablement quelque chose que je n'ai pas sur la façon dont fonctionne CoreAnimation, j'ai effectué des recherches intensives, mais je Je suis coincé avec aucune idée. Quelqu'un sait?

Répondre

24

Si j'ai bien compris votre question, ça va comme ceci. Lorsque vous ajoutez une animation à un CALayer, il crée une copie de présentation de ce calque à l'aide de initWithLayer:. La couche de présentation contient un état animé réel pour chaque image d'animation, tandis que la couche d'origine a l'état final. Le problème avec l'animation de vos propres propriétés est que CALayer ne les copie pas toutes dans initWithLayer:. Si c'est votre cas, vous devez remplacer initWithLayer: et configurer toutes les propriétés dont vous avez besoin pour l'animation, c'est-à-dire à la fois la teinte et le rayon.

+1

Parfait, vous avez raison qui a résolu le problème! Merci beaucoup :) – romrom

+0

De rien! – Costique

+0

C'est vraiment utile. Cela m'a sauvé un jour. – feihu

0
+ (BOOL)needsDisplayForKey:(NSString *)key { 
    if ([key isEqualToString:@"radius"] || [key isEqualToString:@"tint"]) { 
     return YES; 
    } 
    return [super needsDisplayForKey:key]; 
} 

L'animation peut nécessiter que toutes les propriétés du contexte répondent à une actualisation.

+0

Je l'ai déjà essayé, et cela n'a aucun effet. – romrom