2012-03-21 75 views
8

我有一套嵌套的UIView動畫(給定時間深度爲2或3級),我希望能夠暫停和恢復。其中一些動畫使用-animateWithDuration:animations:completion:,而其他動畫則使用-animateWithDuration:delay:options:animations:completion:以延遲動畫塊的執行。使用延遲動畫暫停CALayer動畫

我讀和實現了Technical Q&A QA1673關於暫停層樹中的所有動畫,但我遇到了使用延遲參數的動畫的問題。我可以暫停和恢復動畫,但是當動畫重新開始時,任何與其關聯的延遲的動畫塊的延遲時間延長了層樹暫停的時間。例如,如果其中一個塊的延遲時間爲1秒,並且圖層樹暫停3秒,則動畫在恢復後延遲4秒。我猜這與beginTime屬性有關?任何幫助,將不勝感激。

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

回答

0

我建議採用不同的方法。

動畫塊很容易實現,但只有在您不需要對動畫進行任何控制時纔有用。

否則,您應該使用計時器並手動創建自己的動畫。

[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是一個標誌,控制您的動畫狀態。

+2

感謝您的迴應,但這個想法其實也有它自己的問題。使用標準的「NSTimer」不會將動畫與設備的顯示速率同步,從而導致動畫看起來不連貫。更好的辦法是使用一個'CADisplayLink',它是類似的,但其設計完全是爲了與顯示器同步。儘管如此,使用一個顯示鏈接對象來運行〜10序列化動畫可能會導致一些嚴重的意大利麪代碼。最終,我的問題是*爲什麼*暫停動畫在圖層樹中影響後續*動畫的延遲值?似乎很奇怪,不是嗎? – Sean 2012-03-30 13:11:53

+0

「一些嚴重的意大利麪條代碼」...是的,你是對的......但畢竟我是意大利人;) – Beppe 2012-04-05 19:07:42

0

我找到了解決問題的辦法!您必須在動畫的完成塊中將self.layer.beginTime值重置爲零。

例如

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

其餘的暫停/恢復代碼保持完全相同。

最好!

+0

該死的我希望這會工作......但它不適合我:(,它有現在我決定通過動畫塊去除延遲 – cclogg 2012-07-27 09:34:55

+0

@cclogg如果你有很多在同一層上運行的塊動畫,你必須將它設置爲一次,而不是每個塊動畫:) – Summon 2012-07-27 11:23:02