2012-03-21 12 views
8

Ho una serie di animazioni nidificate UIView (profonde 2 o 3 livelli in un dato momento) che vorrei poter sospendere e riprendere. Alcune di queste animazioni utilizzano -animateWithDuration:animations:completion: mentre altre utilizzano -animateWithDuration:delay:options:animations:completion: per ritardare l'esecuzione del blocco di animazione.Pausa dell'animazione CALayer con un'animazione con un ritardo

Ho letto e implementato Technical Q&A QA1673 sulla sospensione di tutte le animazioni in un albero di livelli, ma sto riscontrando un problema con le animazioni che utilizzano un parametro di ritardo. Posso mettere in pausa e riprendere le animazioni bene, ma quando l'animazione riprende, qualsiasi blocco di animazione che ha un ritardo associato ad esso sembra avere il suo ritardo esteso dalla quantità di tempo in cui l'albero dei livelli è stato messo in pausa. Ad esempio, se uno dei blocchi ha un ritardo di 1 secondo e l'albero dei livelli è stato sospeso per 3 secondi, i ritardi dell'animazione per 4 secondi dopo il riavvio. Immagino che questo abbia qualcosa a che fare con la proprietà beginTime? Qualsiasi aiuto sarebbe apprezzato.

// Pause and Resume methods, right from the technical Q&A 
- (void)pauseAnimationsOnLayer:(CALayer *)layer 
{ 
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; 
    layer.speed = 0.0; 
    layer.timeOffset = pausedTime; 
} 

- (void)resumeAnimationsOnLayer:(CALayer *)layer 
{ 
    CFTimeInterval pausedTime = [layer timeOffset]; 
    layer.speed = 1.0; 
    layer.timeOffset = 0.0; 
    layer.beginTime = 0; 
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; 
    layer.beginTime = timeSincePause; 
} 

// Chained animations 
- (void)animateNextPopup 
{ 
    [UIView animateWithDuration:kRFPVictorySequenceStatePopupDuration 
        animations:^{ 
         [_currentStateImageView setHidden:NO]; 
         [_currentStateImageView setTransform:CGAffineTransformIdentity]; 

        } 
        completion:^(BOOL finished) { 
         [UIView animateWithDuration:kRFPVictorySequenceStateSlideOffDuration 
               delay:kRFPVictorySequenceStateVoteDelay 
              options:UIViewAnimationOptionCurveEaseInOut 
              animations:^{ 
               if (winnerIsDem) { 
                [_currentStateImageView setFrame:CGRectMake(-_currentStateImageView.frame.size.width, 
                           _currentStateImageView.frame.origin.y, 
                           _currentStateImageView.frame.size.width, 
                           _currentStateImageView.frame.size.height)]; 
               } 
               else { 
                [_currentStateImageView setFrame:CGRectMake(1024, 
                           _currentStateImageView.frame.origin.y, 
                           _currentStateImageView.frame.size.width, 
                           _currentStateImageView.frame.size.height)]; 
               } 
              } 
              completion:^(BOOL finished) { 
               // Do some stuff 
              } 
          ]; 
        } 
    ]; 
} 

risposta

0

Suggerisco un approccio diverso.

I blocchi di animazione sono facili da implementare, ma utili solo se non è necessario alcun controllo sull'animazione.

In caso contrario, è necessario utilizzare un timer e creare manualmente le proprie animazioni.

[NSTimer scheduledTimerWithTimeInterval:0.1 
           target:self 
           selector:@selector(timerFired) 
           userInfo:nil 
           repeats:YES]; 

- (void)timerFired 
{ 
    if (isPaused) { 
     // Do nothing 
    } else { 
     // Animate 
    } 
} 

- (IBAction)pauseTapped:(id)sender 
{ 
    if (isPaused) { 
     isPaused = NO; 
    } else { 
     isPaused = YES; 
    } 
} 

isPaused è un flag che controlla il tuo stato di animazione.

+2

Grazie per la risposta, ma questa idea ha in realtà anche i suoi problemi. L'uso di uno standard 'NSTimer' non sincronizzerà l'animazione con la velocità di visualizzazione del dispositivo, il che può far sembrare l'animazione instabile. Meglio sarebbe usare un 'CADisplayLink' che è simile ma progettato esattamente allo scopo di sincronizzarsi con il display. Tuttavia, l'utilizzo di un oggetto link link per eseguire ~ 10 animazioni serializzate potrebbe risultare in qualche serio codice spaghetti. In definitiva, la mia domanda è: * perché * la sospensione delle animazioni in un albero dei livelli influisce sui valori di ritardo per le animazioni * successive *? Sembra strano, no? – Sean

+0

"qualche serio codice spaghetti" ... sì, hai ragione ... ma in fondo sono italiano) – Beppe

0

Ho trovato la soluzione al problema! Devi reimpostare il valore self.layer.beginTime su zero nel blocco di completamento delle animazioni.

ad es.

[UIView animateWithDuration:element.duration 
         delay:element.delay 
        options:UIViewAnimationOptionCurveLinear 
       animations:^{ 
         // Animate properties here! 
        } 
       } completion:^(BOOL finished){ 
           // Reset BeginTime all the time 
           // So, in case a pause took place the delay values are valid again! 
         **self.layer.beginTime = 0.0f;** 
       }]; 

Il resto del codice di pausa/ripresa rimane esattamente lo stesso.

Il migliore!

+0

Darn speravo che funzionasse ... ma non per me :(, aveva nessun effetto Per ora mi sto accontentando di rimuovere il ritardo tramite il blocco di animazione – cclogg

+0

@cclogg se hai molte animazioni di blocchi in esecuzione sullo stesso layer devi impostarlo UNA VOLTA, non in ogni animazione di blocco :) – Summon