2010-10-25 13 views
13

Ho un CALayer personalizzato (ad esempio CircleLayer), contenente proprietà personalizzate (raggio e tinta). Il livello si trasforma nel suo drawInContext: metodo.Perché animare le proprietà personalizzate del CALayer fa sì che altre proprietà siano nulle durante l'animazione?

- (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); 
} 

Voglio la distanza per essere animatable così ho implementato

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

E l'animazione è eseguito in questo modo:

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: viene chiamato come previsto durante l'animazione per ridisegnare il cerchio, tuttavia la tinta è impostata su zero non appena l'animazione inizia e torna al suo valore originale quando termina l'animazione.

Ho concluso che se voglio animare una proprietà personalizzata e voglio che altre proprietà mantengano il loro valore durante l'animazione, devo animarle anch'io, cosa che trovo non conveniente affatto.

Lo scopo non è quello di far crescere/ridurre un cerchio, so che posso usare la trasformazione per questo. È solo per illustrare con un semplice esempio il problema di animare una singola proprietà personalizzata senza dover animare tutte le altre.

Ho fatto un semplice progetto che illustra la questione, che potete trovare qui: Sample project illustrating the issue

Probabilmente c'è qualcosa che non ho avuto su come funziona Core Animation, ho eseguito una ricerca intensiva, ma io' m bloccato senza alcun indizio. Qualcuno lo sa?

risposta

24

Se ho capito bene la tua domanda, va così. Quando aggiungi un'animazione a un CALayer, crea una cosiddetta copia di presentazione di quel livello usando initWithLayer:. Il livello di presentazione contiene lo stato di animazione reale per ciascun fotogramma di animazione, mentre il livello originale ha lo stato finale. Il problema con l'animazione delle tue proprietà è che CALAYER non le copia tutte in initWithLayer:. Se questo è il tuo caso, devi sostituire lo initWithLayer: e impostare tutte le proprietà necessarie per l'animazione, ovvero sia la tinta che il raggio.

+1

Perfetto hai ragione che ha risolto il problema! Grazie mille :) – romrom

+0

Prego! – Costique

+0

Questo è davvero utile. Mi ha salvato un giorno. – feihu

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

L'animazione può richiedere che tutte le proprietà del contesto rispondano a un aggiornamento.

+0

L'ho già provato e non ha alcun effetto. – romrom

Problemi correlati