2012-02-14 33 views
11

我有一個圖像數組加載到UIImageView,我通過一個循環動畫。在顯示圖像後,我想要調用@selector以關閉當前的視圖控制器。使用此代碼的圖像動畫很好:UIImageView動畫完成後的訪問方法

NSArray * imageArray = [[NSArray alloc] initWithObjects: 
         [UIImage imageNamed:@"HowTo1.png"], 
         [UIImage imageNamed:@"HowTo2.png"], 
         nil]; 
UIImageView * instructions = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

instructions.animationImages = imageArray; 
[imageArray release]; 
instructions.animationDuration = 16.0; 
instructions.animationRepeatCount = 1; 
instructions.contentMode = UIViewContentModeBottomLeft; 
[instructions startAnimating]; 
[self.view addSubview:instructions]; 
[instructions release]; 

在16秒後,我想要一個方法被調用。我看着UIView類的方法setAnimationDidStopSelector:,但我無法讓它與我目前的動畫實現一起工作。有什麼建議麼?

謝謝。

回答

22

使用performSelector:withObject:afterDelay:

[self performSelector:@selector(animationDidFinish:) withObject:nil 
    afterDelay:instructions.animationDuration]; 

或使用dispatch_after

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, instructions.animationDuration * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    [self animationDidFinish]; 
}); 
+0

我用第一種方法去了,謝謝。 – 2012-02-14 21:48:34

+0

這種方法似乎工作正常,感謝搶劫!但我想知道如果由於某種原因iPhone的幀速下降會發生什麼。可以說從30到15.在這種情況下,當調度定時器運行不正常時,動畫不會完成播放? – Tieme 2012-12-18 08:12:14

+0

爲什麼你認爲幀率下降會使動畫花費更長的時間?如果圖像視圖無法跟上,可能會丟失幀。 – 2012-12-18 08:17:19

3

您可以創建一個計時器在動畫持續時間後觸發。回調可以處理動畫完成後要執行的邏輯。在您的回撥中,請務必檢查動畫[UIImageView isAnimating]的狀態,以防萬一您需要更多時間讓動畫完成。

1

在ImageView.m

- (void) startAnimatingWithCompleted:(void (^)(void))completedHandler { 
if (!self.isAnimating) { 
    [self startAnimating]; 
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, self.animationDuration * NSEC_PER_SEC); 
    dispatch_after(popTime, dispatch_get_main_queue(),completedHandler);  
}} 
8

有沒有辦法做到這一點恰恰與UIImageView的。使用延遲將在大部分時間都有效,但開始後可能會有一些延遲動畫在屏幕上發生之前調用動畫,因此它不精確。而不是使用UIImageView進行動畫嘗試使用CAKeyframeAnimation,它將在動畫完成時調用委託方法。沿着這些路線的東西:

NSArray * imageArray = [[NSArray alloc] initWithObjects: 
        (id)[UIImage imageNamed:@"HowTo1.png"].CGImage, 
        (id)[UIImage imageNamed:@"HowTo2.png"].CGImage, 
        nil]; 
UIImageView * instructions = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

//create animation 
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation]; 
[anim setKeyPath:@"contents"]; 
[anim setValues:imageArray]; 

[anim setRepeatCount:1]; 
[anim setDuration:1]; 
anim.delegate = self; // delegate animationDidStop method will be called 

CALayer *myLayer = instructions.layer; 

[myLayer addAnimation:anim forKey:nil]; 

然後,只需執行animationDidStop委託方法

+0

無法將CGImage添加到數組。 – 2013-09-25 13:47:35

+0

爲了擺脫由於將CGImage添加到數組而導致的警告,只需將其轉換爲id即可。 – 2013-10-01 19:21:33

+0

編輯以反映上面的答案。參見[蘋果文檔](https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CAKeyframeAnimation_class/Introduction/Introduction.html#//apple_ref/occ/instp/CAKeyframeAnimation/values)。 – 2013-10-01 19:33:46

4

用這種方法你避免計時器火,而ImageView的仍然動畫由於緩慢的圖像加載。 你可以用這種方法同時使用performSelector: withObject: afterDelay:和GCD:

[self performSelector:@selector(didFinishAnimatingImageView:) 
      withObject:imageView 
      afterDelay:imageView.animationDuration]; 

/\self.imageView.animationDurationstartAnimating之前打賭配置,否則這將是0

比如果-(void)didFinishAnimatingImageView:創建一個後臺隊列,執行檢查isAnimating財產,比執行主隊列上的其餘部分

- (void)didFinishAnimatingImageView:(UIImageView*)imageView 
{ 

    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.yourcompany.yourapp.checkDidFinishAnimatingImageView", 0); 
    dispatch_async(backgroundQueue, ^{ 

     while (self.imageView.isAnimating) 
      NSLog(@"Is animating... Waiting..."); 

     dispatch_async(dispatch_get_main_queue(), ^{ 

      /* All the rest... */ 

     }); 

    }); 

} 
+0

簡單的解決方案,像魅力一樣工作 – 2016-06-08 08:27:41

20

您可以imple使用這一類UIImageView-AnimationCompletionBlock

而對於斯威夫特版本:UIImageView-AnimationImagesCompletionBlock

採取此類中自述文件看看..

添加的UIImageView + AnimationCompletion.h的UIImageView + AnimationCompletion。米文件的項目,並將其導入的UIImageView + AnimationCompletion.h文件要使用這個..

對於如。

NSMutableArray *imagesArray = [[NSMutableArray alloc] init]; 
for(int i = 10001 ; i<= 10010 ; i++) 
    [imagesArray addObject:[UIImage imageNamed:[NSString stringWithFormat:@"%d.png",i]]]; 

self.animatedImageView.animationImages = imagesArray; 
self.animatedImageView.animationDuration = 2.0f; 
self.animatedImageView.animationRepeatCount = 3; 
[self.animatedImageView startAnimatingWithCompletionBlock:^(BOOL success){ 
NSLog(@"Animation Completed",);}]; 
+0

謝謝!這很棒。 – daspianist 2014-04-06 05:52:46

+0

這應該是被接受的答案 – 2cupsOfTech 2014-12-10 17:30:30

+0

我無法弄清楚如何在swift中使用它。添加到橋接頭後,它仍然不起作用。 – 2015-04-23 00:34:50

0

從GurPreet_Singh答(UIImageView的+ AnimationCompletion) 創建斯威夫特版本我沒能創造一個UIImageView的擴展,但我相信這是非常簡單易用。

class AnimatedImageView: UIImageView, CAAnimationDelegate { 

    var completion: ((_ completed: Bool) -> Void)? 

    func startAnimate(completion: ((_ completed: Bool) -> Void)?) { 
     self.completion = completion 
     if let animationImages = animationImages { 
      let cgImages = animationImages.map({ $0.cgImage as AnyObject }) 
      let animation = CAKeyframeAnimation(keyPath: "contents") 
      animation.values = cgImages 
      animation.repeatCount = Float(self.animationRepeatCount) 
      animation.duration = self.animationDuration 
      animation.delegate = self 

      self.layer.add(animation, forKey: nil) 
     } else { 
      self.completion?(false) 
     } 
    } 

    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { 
     completion?(flag) 
    } 
} 


let imageView = AnimatedImageView(frame: CGRect(x: 50, y: 50, width: 200, height: 135)) 
imageView.image = images.first 
imageView.animationImages = images 
imageView.animationDuration = 2 
imageView.animationRepeatCount = 1 
view.addSubview(imageView) 

imageView.startAnimate { (completed) in 
    print("animation is done \(completed)") 
    imageView.image = images.last 
}