如何取消UIView基于块的动画?

94
我已经搜索了很多关于SO的内容和苹果的参考文献,但仍然无法解决我的问题。
我有:
1. 一个屏幕,其中包含2个UIImageView和2个与它们连接的UIButton。 2. 两种动画:
- 每个图像依次放大然后缩小,仅在viewDidLoad中执行一次。 - 当按下按钮(每个UIImageView内部隐藏的自定义按钮)时,它会触发相应UIImageView的动画 - 只有一个,而不是两个 - (也是先放大然后缩小)。 - 因为我正在为iOS4+编写,所以被告知要使用基于块的动画!
我需要:
如何取消正在运行的动画?我已经设法在最后一个之后取消了... :/
这是我的代码片段:
[UIImageView animateWithDuration:2.0 
                               delay:0.1 
                             options:UIViewAnimationOptionAllowUserInteraction 
                          animations:^{
        isAnimating = YES;
        self.bigLetter.transform = CGAffineTransformScale(self.bigLetter.transform, 2.0, 2.0);
    } completion:^(BOOL finished){
        if(! finished) return;
        [UIImageView animateWithDuration:2.0 
                                   delay:0.0 
                                 options:UIViewAnimationOptionAllowUserInteraction 
                              animations:^{
            self.bigLetter.transform = CGAffineTransformScale(self.bigLetter.transform, 0.5, 0.5);
        } completion:^(BOOL finished){
            if(! finished) return;
            [UIImageView animateWithDuration:2.0 
                                       delay:0.0 
                                     options:UIViewAnimationOptionAllowUserInteraction 
                                  animations:^{
                self.smallLetter.transform = CGAffineTransformScale(self.smallLetter.transform, 2.0, 2.0);
            } completion:^(BOOL finished){
                if(! finished) return;
                [UIImageView animateWithDuration:2.0 
                                           delay:0.0 
                                         options:UIViewAnimationOptionAllowUserInteraction 
                                      animations:^{
                    self.smallLetter.transform = CGAffineTransformScale(self.smallLetter.transform, 0.5, 0.5);
                }
                                      completion:^(BOOL finished){
                                          if (!finished) return;
                                          //block letter buttons
                                          [self.bigLetterButton setUserInteractionEnabled:YES];
                                          [self.smallLetterButton setUserInteractionEnabled:YES];
                                          //NSLog(@"vieDidLoad animations finished");
                                      }];
            }];
        }];
    }];

一些方式下,smallLetter UIImageView不能正常工作,因为在按下时(通过按钮),bigLetter可以正确地取消动画... 编辑:我已经使用了这个解决方案,但是缩小smallLetter UIImageView仍然存在问题-根本不会取消...solution 编辑2:我已经在下一个/上一个方法的开头添加了这个:
- (void)stopAnimation:(UIImageView*)source {
    [UIView animateWithDuration:0.01
                          delay:0.0 
                        options:(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction)
                     animations:^ {
                         source.transform = CGAffineTransformIdentity;
                     }
                     completion:NULL
     ];
}

问题仍然存在... :/ 不知道如何打断动画链中的最后一个字母动画


嘿,我认为应该现在接受Hari Kunwar的答案。 - marczellm
现在必须使用UIViewPropertyAnimator - 它非常容易使用。 - Fattie
4个回答

161

您可以通过调用以下代码停止视图上的所有动画:

[view.layer removeAllAnimations];
(您需要导入QuartzCore框架才能在视图层上调用方法。)
如果您想要停止特定的动画而不是所有动画,最好使用CAAnimations显式地而非UIView动画辅助方法,这样您将拥有更细粒度的控制,并可以根据名称显式地停止动画。
苹果的核心动画文档可以在此处找到: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CreatingBasicAnimations/CreatingBasicAnimations.html

13
我想补充一点,我自己观察到,在调用removeAllAnimations后,后续的animateWithDuration将不再起作用。这是用于分页和下拉刷新控件的情况,也许其他人可能会有不同的观察结果。最终,我使用了CABasicAnimation,并调用[myView.layer removeAnimationForKey:@"animationKey"]。 - Zhang
感谢@Nick的提示 - 只是提醒一下,链接似乎不再受支持,请尝试使用此链接:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/CreatingBasicAnimations/CreatingBasicAnimations.html - trdavidson
在 view.layer.removeAllAnimations() 之后添加动画视图无法正常工作。 - Bunthoeun

72

对于 iOS 10,使用 UIViewPropertyAnimator 来进行动画处理。它提供了开始、停止和暂停 UIView 动画的方法。

 let animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeOut){
        self.view.alpha = 0.0
 }
 // Call this to start animation.
 animator.startAnimation()

 // Call this to stop animation.
 animator.stopAnimation(true)

1
在新代码中添加一个引人注目的评论,非常相关的答案。 - Oded Ben Dov

4
我补充一下Nick的答案,为了使removeAllAnimations平滑,下一个想法会非常方便。
[view.layer removeAllAnimations];
[UIView transitionWithView:self.redView
                  duration:1.0f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
                      [view.layer displayIfNeeded];
                  } completion:nil];

0
你可以尝试这个(使用Swift):
UIView.setAnimationsEnabled(false)
UIView.setAnimationsEnabled(true)

注意:如果需要,您可以在这两个调用之间放置代码,例如:
UIView.setAnimationsEnabled(false)
aview.layer.removeAllAnimations() // remove layer based animations e.g. aview.layer.opacity
UIView.setAnimationsEnabled(true)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接