2012-02-14 24 views
11

Tôi có một loạt ảnh được tải vào UIImageView mà tôi đang tạo hoạt ảnh thông qua một chu kỳ. Sau khi hình ảnh đã được hiển thị, tôi muốn một số @selector được gọi để loại bỏ trình điều khiển chế độ xem hiện tại. Các hình ảnh hoạt hình tốt với mã này:Phương thức truy cập Sau khi kết thúc hoạt ảnh 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]; 

Sau 16 giây, tôi muốn có phương thức được gọi. Tôi đã xem xét phương thức lớp học UIViewsetAnimationDidStopSelector: nhưng tôi không thể làm cho nó hoạt động với triển khai hoạt ảnh hiện tại của mình. Bất kỳ đề xuất?

Cảm ơn.

Trả lời

22

Sử dụng performSelector:withObject:afterDelay::

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

hoặc sử dụng 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

Tôi đã sử dụng phương pháp đầu tiên, cảm ơn. –

+0

Phương pháp này dường như hoạt động tốt, cảm ơn cướp! Nhưng tôi đã tự hỏi điều gì sẽ xảy ra nếu vì một lý do nào đó tốc độ khung hình của iPhone giảm rất nhiều. Cho phép nói từ 30 đến 15. Trong trường hợp đó, hoạt ảnh sẽ không được hoàn thành khi phát bộ đếm thời gian của công cụ chạy phải không? – Tieme

+0

Tại sao bạn cho rằng việc giảm tốc độ khung hình sẽ khiến hoạt ảnh mất nhiều thời gian hơn? Có thể chế độ xem hình ảnh sẽ giảm khung nếu không thể theo kịp. –

3

Bạn có thể tạo bộ hẹn giờ để kích hoạt sau khoảng thời gian hoạt ảnh của mình. Cuộc gọi lại có thể xử lý logic của bạn mà bạn muốn thực thi sau khi hoạt ảnh kết thúc. Trong gọi lại của bạn hãy chắc chắn kiểm tra tình trạng của các hình ảnh động [UIImageView isAnimating] chỉ trong trường hợp bạn muốn có thêm thời gian để cho kết thúc hoạt hình.

1

trong 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

Không có cách nào để làm điều này một cách chính xác với UIImageView. Sử dụng một sự chậm trễ sẽ làm việc hầu hết thời gian, nhưng có thể có một số tụt hậu sau khi startAnimating được gọi trước khi các hình ảnh động xảy ra trên màn hình để nó không chính xác. Thay vì sử dụng UIImageView cho hoạt ảnh này, hãy thử sử dụng CAKeyframeAnimation sẽ gọi phương thức ủy nhiệm khi hoạt ảnh kết thúc. Một cái gì đó dọc theo những dòng:

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

Sau đó chỉ cần thực hiện các phương pháp animationDidStop đại biểu

+0

Không thể thêm CGImage vào mảng. –

+0

Để loại bỏ cảnh báo gây ra bằng cách thêm CGImage vào một mảng chỉ cần đưa nó vào id. –

+0

Trả lời chỉnh sửa để phản ánh ở trên. Xem [doc tài liệu] (https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CAKeyframeAnimation_class/Introduction/Introduction.html#//apple_ref/occ/instp/CAKeyframeAnimation/values). –

4

Với phương pháp này bạn tránh giờ để bắn trong khi IMAGExem vẫn sinh động do chậm hình ảnh tải. Bạn có thể sử dụng cả hai performSelector: withObject: afterDelay: và GCD theo cách này:

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

/\self.imageView.animationDuration có đặt cược cấu hình trước startAnimating, nếu không nó sẽ là 0

hơn nếu -(void)didFinishAnimatingImageView: tạo một hàng đợi nền, thực hiện séc trên tài sản isAnimating, so với thực hiện phần còn lại trên hàng đợi chính

- (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

Giải pháp đơn giản, hoạt động như nét duyên dáng –

20

Bạn có thể imple sử dụng loại này UIImageView-AnimationCompletionBlock

Và đối với Swift phiên bản: UIImageView-AnimationImagesCompletionBlock

Hãy xem trong hồ sơ Readme trong lớp này ..

Thêm UIImageView + AnimationCompletion.hUIImageView + AnimationCompletion.m tệp trong dự án và chúng nhập UIImageView + AnimationCompletion.h tệp nơi bạn muốn sử dụng này ..

Ví dụ:

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

Cảm ơn bạn! Điều đó thật tuyệt. – daspianist

+0

đây phải là câu trả lời được chấp nhận – 2cupsOfTech

+0

Tôi không thể tìm ra cách sử dụng điều này nhanh chóng. Sau khi thêm vào tiêu đề bắc cầu nó vẫn không hoạt động. –

0

Created Swift Version từ GurPreet_Singh trả lời (UIImageView + AnimationCompletion) Tôi đã không thể tạo ra một phần mở rộng cho UIImageView nhưng tôi tin rằng điều này là đủ đơn giản để sử dụng.

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 
} 
Các vấn đề liên quan