2013-03-19 2 views
2

Dans une sous-classe UIView, j'ai cette méthode:Pourquoi manque-t-il une animation implicite lorsque j'ajoute une sous-couche à une couche?

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

Qu'est-ce que je manque? Je m'attends à ce que l'opacité de CALayer layer soit implicitement animée avec la dernière ligne de cette méthode.

Ma solution

Voici comment je résolu le problème grâce à la réponse de Duncan.

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

} 

Vous avez seulement besoin de mettre la création de la couche et la modifiction de l'opacité dans deux blocs de CATransaction différents. Cependant, déplacer la création (et non l'ajout) de la couche vers la méthode layerFactory ne change rien à la situation.

Je ne sais pas si c'est la meilleure solution, mais ça marche.

+0

Cela signifie-t-il que des animations implicites peuvent être effectuées sur une sous-couche de la couche UIView principale, mais sur la couche elle-même? – Sam

+0

La réponse acceptée est incorrecte. Voir la bonne réponse ici: http://stackoverflow.com/a/10456080/56149. – an0

+0

duplication possible de [l'animation implicite Core Animation ne se déclenche pas sauf dans la boucle d'événements] (http://stackoverflow.com/questions/10456022/core-animation-implicit-animation-doesnt-fire-unless-in-event-loop) – an0

Répondre

4

Vous ne pouvez pas créer de calque et définir son opacité, puis définir l'opacité sur une nouvelle valeur dans la même méthode et obtenir une animation implicite. Essayez de placer votre code de couche de création/configuration dans un bloc begin/end de CATransaction, puis le code pour définir l'opacité à 1 dans un autre bloc de début/fin de transaction.

Je pense que cela fonctionnera, mais je devrais essayer pour être sûr. Si cela ne fonctionne pas, appelez le code pour définir l'opacité sur 1 en utilisant performSelector: withObject: afterDelay et une valeur de retard de 0. Cela permettra au système d'ajouter votre couche avec une opacité de 0, puis traiter le changement d'opacité à 1 en tant que transaction séparée.

Questions connexes