2011-04-21 74 views
0

我有一個UIView動畫(由touchesEnded:事件調用),我想在允許更多用戶輸入之前完成執行。在動畫被調用之前,我檢查一個標誌「isMoving」以查看動畫是否正在進行。然後我設置isMovingYES並執行如下動畫(是的,我知道這是不是塊格式)...在UIView動畫期間防止用戶輸入

- (void) methodCalledFromViewControllerTouchesEnded { 
    if (isMoving == YES) { 
     NSLog (@"Don't start another animation!"); 
     return; 
    } 
    isMoving = YES; 

    ...... 

    [UIView beginAnimations:@"move" context:NULL]; 
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; 
    [UIView setAnimationDuration:0.25f]; 
    ... 
    // DO MOVE STUFF 
    ... 
    [UIView commitAnimations]; 

    isMoving = NO; 
} 

然後我設置isMovingNO所以後續調用從touchesEnded:不啓動另一個動畫而目前正在進行中。但是,如果用戶在初始動畫進行過程中保持觸摸,則會重複執行此FAILS和動畫。

我不知道這是否有可能觸摸事件是在不同的線程上處理的,而不是動畫。

我也跑在調試模式下,發現該動畫實際上不是「提交」,直到控制已經離開methodCalledFromViewControllerTouchesEnded,回到touchesEnded:,從而使該isMoving = NO;標誌形同虛設。

任何幫助防止重複的動畫將不勝感激。

回答

6

如果您使用的UIView的類方法

+ (void)animateWithDuration:(NSTimeInterval)duration 
       animations:(void (^)(void))animations 

用戶交互默認情況下禁用,直到動畫完成。這會爲你節省很多工作。對於你來說,你會想要使用完整的方法,以便使用你的EaseIn選項。它看起來像這樣

- (void) methodCalledFromViewControllerTouchesEnded { 

     [UIView animateWithDuration:0.25f 
           delay:0.0 
          options:UIViewAnimationOptionCurveEaseIn 
         animations:^(void){ 
            // You animations here 
         } 
         completion: nil]; 

} 

如果按照你現在的樣子,你需要改變一些東西。請記住,動畫沒有被阻擋,因此當您在最後將isMoving設置爲NO時,動畫會在動畫開始後立即發生,而不是在結束後發生。現在讓我重申一下,上面的代碼比你的方法簡單得多,但是如果你想繼續下去,你需要爲動畫設置animationStopped完成方法,並且在該方法中,將isMoving設置爲NO。它應該是這樣的:

isMoving = YES; 
[UIView beginAnimations:@"move" context:NULL]; 
//... 
[UIView setAnimationDidStopSelection:@selector(animationDidStop:finished:context:)]; 
// ... DO MOVE STUFF 
//.... 
[UIView commitAnimations]; 

然後你會實現這樣的選擇:

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context 
{ 
    isMoving = NO; 
} 
+0

完美!我一直在嘲笑我的頭數超過我想要承認的時間!我一直在避免轉換到這裏顯示的塊格式,因爲我有幾個將不得不效仿。但現在我想這將是值得的!我欠你一杯啤酒。 – 2011-04-21 18:50:04

+0

我編輯了我的答案,以非塊方式向您展示。 – Christian 2011-04-21 18:54:18

1

你的東西是正確的,除非你誤解如何動畫作品。它正如你所說的那樣工作:P。

問題是,您設置isMoving爲過早。動畫塊不會暫停執行代碼。相反,它排隊動畫並繼續執行。

- (void) methodCalledFromViewControllerTouchesEnded { 
    if (isMoving == YES) { 
     NSLog (@"Don't start another animation!"); 
     return; 
    } 
    isMoving = YES; 

    [UIView animateWithDuration:.25 
         animations:^(void){ 
            //DO STUFF HERE 
         } 
         completion: ^(BOOL finished) { 
            isMoving = NO; 
         }]; 
} 

更多的是你想要的。

如果你真的不想做塊結構。然後用東西去像

- (void) methodCalledFromViewControllerTouchesEnded { 
    if (isMoving == YES) { 
     NSLog (@"Don't start another animation!"); 
     return; 
    } 
    isMoving = YES; 

    ...... 

    [UIView beginAnimations:@"move" context:NULL]; 
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; 
    [UIView setAnimationDuration:0.25f]; 
    [UIView setAnimationDelegate:self]; 
    [UIView setAnimationDidStopSelector:@selector(animate:finished:context:)]; 
    ... 
    // DO MOVE STUFF 
    ... 
    [UIView commitAnimations]; 

} 

-(void)animate:(NSString *)str_animationID finished:(BOOL)b_isFinished context:(void *)v_context { 

    if(str_animationID == @"move") { 
     isMoving = NO; 
    } 
} 
+0

只需要注意上面的代碼,默認情況下UIView的塊動畫會阻止用戶交互,所以上面的代碼是矯枉過正的。要在動畫期間啓用用戶交互,您需要完整的塊動畫方法,並將UIViewAnimationOptionAllowUserInteraction作爲其中一個選項傳遞。 – Christian 2011-04-21 18:56:13

+0

+1非常好。謝謝。然而,我剛剛將答案交給了基督徒,正如他首先提出的。 – 2011-04-21 18:57:29

+0

是的,沒關係。只是想給你你失蹤的信息:P。我記得當我第一次開始UIView動畫時(WAYYYYY在塊被實現之前)我想哭。至於它是「過度殺傷」,對於這個具體的實施來說也是如此。您可能希望用更重要的動畫重載動畫。我在我的應用程序中經常這樣做。所以即使發生動畫也能夠指定動畫。 – ColdLogic 2011-04-21 19:31:21

4

我有一個類似的問題,以解決它:

[[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 
[[UIApplication sharedApplication] endIgnoringInteractionEvents]; 
+0

這是我認爲的最佳答案。 – 2014-04-11 11:33:19