2012-03-21 23 views
8

Bir duraklatmak ve devam ettirmek isteyebileceğim bir dizi iç içe geçmiş UIView animasyonları (belirli bir zamanda 2 veya 3 seviye derinlikte) var. Bu animasyonlardan bazıları, -animateWithDuration:animations:completion:, diğerleri ise animasyon bloğunun yürütülmesini geciktirmek için -animateWithDuration:delay:options:animations:completion: kullanır.CALayer animasyonunu gecikmeli bir animasyonla duraklatıyor

Bir katman ağacındaki tüm animasyonları duraklatma hakkında Technical Q&A QA1673 okuyup uyguladım, ancak gecikme parametresi kullanan animasyonlarla ilgili bir sorunla karşılaşıyorum. Animasyonları yalnızca iyi bir şekilde duraklatabilir ve devam ettirebilirim, ancak animasyon devam ettiğinde, onunla ilişkili bir gecikme yaşanmış olan herhangi bir animasyon bloğunun, katman ağacının duraklatıldığı süreye göre gecikmesini uzatmış gibi görünüyor. Örneğin, bloklardan birinin 1 saniyelik bir gecikme varsa ve katman ağacı 3 saniyeliğine duraklatılmışsa, animasyon devam ettikten sonra 4 saniye geciktirilir. Sanırım bu, beginTime mülküyle ilgili bir şey var mı? Herhangi bir yardım takdir edilecektir.

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

cevap

0

Farklı bir yaklaşım öneririm.

Animasyon bloklarının uygulanması kolaydır, ancak yalnızca animasyonunuz üzerinde herhangi bir kontrole ihtiyaç duymazsanız kullanışlıdır. Aksi takdirde, bir zamanlayıcı kullanmalı ve kendi animasyonunuzu manuel olarak oluşturmalısınız.

[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

animasyon durumunu kontrol eden bayrağıdır.

+2

Yanıt için teşekkürler, ancak bu fikrin aslında kendi sorunları vardır. Standart bir 'NSTimer' kullanmak, animasyonu cihazın görüntülenme hızıyla senkronize etmeyecek ve bu da animasyonun dalgalı görünmesine neden olabilir. Daha iyisi, benzer olan ancak ekranla senkronizasyon amacıyla tam olarak tasarlanmış bir "CADisplayLink" kullanmak olacaktır. Yine de, ~ 10 seri hale getirilmiş animasyonlar çalıştırmak için bir ekran bağlantı nesnesi kullanarak bazı ciddi spagetti kodu ortaya çıkabilir. Son olarak, sorum şu: * bir katman ağacındaki animasyonları neden duraklatıyor * * sonraki animasyonlar için gecikme değerlerini etkiler mi? Tuhaf görünüyor, değil mi? – Sean

+0

"bazı ciddi spagetti kodları" ... evet, haklısın ... ama hepsinden sonra ben İtalyan'ım;) – Beppe

0

Sorunun çözümünü buldum! Animasyonlarınızın tamamlama bloğunda self.layer.beginTime değerini sıfırlamanız gerekir.

örn.

[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;** 
       }]; 

Duraklama/sürdürme kodunun geri kalanı tam olarak aynı kalır.

En İyi!

+0

Darn Bunun işe yaracağını umuyordum ... ama benim için yapmadı :(Şimdi hiçbir zaman animasyon bloğu üzerinden gecikmeyi kaldırmaya karar veriyorum. – cclogg

+0

@cclogg Eğer aynı katman üzerinde çalışan çok sayıda blok animasyonunuz varsa, her blok animasyonunda değil, ONCE ayarlamanız gerekir :) – Summon