2010-06-14 5 views
0

J'ai eu quelques problèmes avec l'animation de plusieurs CALayers en même temps, et j'espérais que quelqu'un pourrait me diriger dans la bonne direction.CALayer: rappel à la fin de l'animation?

Mon application contient un tableau de CALayer. La position de chaque couche est définie sur (previousLayer.position.y + previousLayer.bounds.height), ce qui les définit essentiellement comme une table. J'ai alors une méthode qui, chaque fois qu'on l'appelle, ajoute une nouvelle couche à la pile et définit sa position Y à 0. Les positions Y de toutes les autres couches du tableau sont alors compensées par la hauteur du nouveau. couche (poussant essentiellement toutes les vieilles couches vers le bas). Ce qui me pose problème, c'est d'empêcher l'ajout de nouveaux calques jusqu'à la fin de l'animation précédente.

Existe-t-il un moyen de savoir quand une animation implicite est terminée? Ou bien, si j'utilise CABasicAnimation et animationDidFinish, est-il possible de dire quel objet a fini d'animer quand animationDidFinish est appelée?

Répondre

0

Il s'est avéré que plutôt que d'ajouter CABasicAnimation directement au CALayer, j'ai dû l'ajouter au dictionnaire 'actions' du calque ... Cela laisse la couche à sa position finale après la fin de l'animation, mais appelle Méthode 'animationDidFinish'.

-(void)startAnimation { 
    if(!animating){ 
     animating = YES; 
     for(int i=0; i<[tweets count]; i++) { 
      //get the layer 
      CETweetLayer *currentLayer = [tweets objectAtIndex:i]; 

      //setup the orgin and target y coordinates 
      float targetY = currentLayer.position.y + offset; 

     //setup the animation 
     CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; 
     anim.delegate = self; 
     currentLayer.actions = [NSDictionary dictionaryWithObject:anim forKey:@"position"]; 
     currentLayer.position = CGPointMake(self.bounds.size.width/2, targetY); 
    } 
    } 
} 

Et puis ...

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 
    animating = NO; 
} 
4

Vous pouvez définir des valeurs arbitraires pour les clés de votre objet d'animation. Ce que cela signifie est que vous pouvez associer votre calque que vous animez avec l'animation, puis interroger dans -animationDidStop: terminé: Vous créez votre animation de cette façon:

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; 
// set other fields... 

[anim setValue:layerToAnimate forKey:@"layer"]; 

// Start the animation 
[layerToAnimate addAnimation:anim forKey:nil]; 

Vérifiez ensuite pour cette valeur lorsque l'animation arrête:

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag 
{ 
    CALayer *animatedLayer = [animation valueForKey:@"layer"]; 
    // do something with the layer based on some condition... 
    // spin off the next animation... 

    [CATransaction begin]; 
    [CATransaction setValue:(id)kCFBooleanTrue 
       forKey:kCATransactionDisableActions]; 
    [animatedLayer setPosition:position]; 
    [CATransaction commit]; 
} 

Ceci est une animation explicite, mais elle devrait vous donner ce dont vous avez besoin.

+0

Cela a fonctionné principalement. Le code est appelé, et je peux récupérer l'objet layer à partir de la clé. Mais j'éprouve un effet de scintillement lorsque j'essaie de placer layer.position à la position à laquelle le calque est supposé être à la fin de l'animation. Il semble que l'animation se termine et que la position de la couche soit rétablie à la position d'origine avant que mon 'layer.position =' soit appelé. Une idée de comment je peux contourner ça? – carloe

+0

Oui. Si vous voulez définir la propriété position à la fin de l'animation, vous devrez désactiver l'animation implicite dans une transaction de votre méthode -animationDidStop: finished:. Je mettrai à jour ma réponse avec le code pertinent. –

+0

Le code que vous avez posté est identique à ce que j'avais et a causé des scintillements. J'ai juste compris comment contourner cela et posterai le code en une seconde. Merci pour votre aide! – carloe

1

Vous pouvez essayer autour de votre code dans un CATransaction. Voici à quoi cela ressemblerait dans Swift 3:

CATransaction.begin() 
CATransaction.setCompletionBlock({ 
    // run after the animations 
}) 
// animtations 
CATransaction.commit() 
+0

Ceci est la solution la plus propre ici et fonctionne très bien. –