我有一个图像数组加载到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:
,但我无法使用它来处理当前的动画实现。有什么建议吗?
感谢。
答案 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)
- (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);
}}