UIImageView动画完成后的访问方法

时间:2012-02-14 19:50:29

标签: iphone objective-c animation uiview uiimageview

我有一个图像数组加载到UIImageView中,我通过一个循环动画。显示图像后,我希望调用@selector以关闭当前视图控制器。使用以下代码对图像进行动画处理:

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:,但我无法使用它来处理当前的动画实现。有什么建议吗?

感谢。

7 个答案:

答案 0 :(得分:23)

使用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];
});

答案 1 :(得分:20)

您可以简单地使用此类别UIImageView-AnimationCompletionBlock

对于 Swift 版本:UIImageView-AnimationImagesCompletionBlock

查看本课程中的自述文件..

在项目中添加 UIImageView + AnimationCompletion.h UIImageView + AnimationCompletion.m 文件,然后导入 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",);}];

答案 2 :(得分:8)

使用UIImageView无法做到这一点。使用延迟大部分时间都可以工作,但是在动画发生在屏幕上之前调用startAnimating后可能会有一些延迟,所以它不精确。而不是使用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委托方法

答案 3 :(得分:4)

使用此方法可以避免在imageView因图像加载速度较慢而仍处于动画状态时触发定时器。 您可以这样使用performSelector: withObject: afterDelay:和GCD:

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

/!\ self.imageView.animationDuration必须在startAnimating之前配置,否则将为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... */

       });

   });

}

答案 4 :(得分:3)

您可以创建一个计时器,以便在动画持续时间后触发。回调可以处理动画结束后要执行的逻辑。在回调中,请确保检查动画[UIImageView isAnimating]的状态,以防您想要更多时间让动画完成。

答案 5 :(得分:3)

从GurPreet_Singh创建Swift版本答案(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
}

答案 6 :(得分: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);       
}}