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

20

我目前关注以下问题:

我启动了一项动画,其中触发了2个对象属性。

代码如下:

    [UIView animateWithDuration:0.3 animations:^{
        greyscaleImage.alpha     = 1;
        activityIndicator.alpha  = 1;
    } completion:^(BOOL f){
        if(f)
        {
            [activityIndicator startAnimating];
        }
    }];

代码本身没有问题。

唯一的问题是当包含此activityIndicator和greyscaleImage的视图被释放时,我发现有0.3秒的时间来崩溃应用程序。

为了更清楚地说明,请想象一个ViewController,它的视图通过默认的iOS模态视图方式呈现。现在触发那个需要2分钟的动画。在达到2分钟之前,你发现这个动画非常无聊,想要关闭这个视图。现在,视图、activityIndicator和greyscaleImage都已释放,动画当然不知道该怎么做了。

所以我想知道,在这里该怎么做,以及为什么调试器会指向它。

  } completion:^(BOOL f){

有没有办法让用户在两分钟结束之前关闭视图?

最好的问候


1
可能是如何取消UIView基于块的动画?的重复问题。 - Vladimir
4个回答

32

如果你开始一个新动画,持续0.0秒并到达你想要到达的状态,它将取消旧动画并启动新的(即时)“动画”。

以下是一个例子,当你想通过到达已经存在的位置来停止移动视图时:

[UIView animateWithDuration:0.0
                      delay:0.0
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{movingView.frame = ((CALayer *)movingView.layer.presentationLayer).frame;}
                 completion:^(BOOL finished){}
 ];

选项:UIViewAnimationOptionBeginFromCurrentState很重要。不调用它将让您的动画从前一个动画的结束状态开始。在移动中,它会先跃到最终位置,然后再跃到您希望停止的位置。即使您的取消“动画”是瞬时的,来回跳动也可能会可见。

注意:动画时间并不一定是0.0秒,任何动画都会取消旧动画。不过对于不同类型的动画,我不太确定。例如,我不知道更改帧是否会停止淡入淡出。


谢谢!我刚刚注意到,设置其中一个更改的属性也取消了块执行。非常感谢。 - thedanielhanke
请注意,对我来说,“设置已更改的属性之一”并没有“取消块执行”(这是无意义的,因为块执行无法被取消),也没有取消正在进行的动画。 - Ricardo Sanchez-Saez

7
您可以从视图层中删除所有动画。
[movingView.layer removeAllAnimations];

2
@Ninja- removeAllAnimations尚未从API中删除,因此它应该可以工作。https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CALayer_class/index.html - Chris
对我来说不起作用。它仍然在开始之前等待先前的动画持续时间。 - Dan

1

设置动画选项UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction对我有用。

像这样使用:

[UIView animateWithDuration:0.5
                          delay:0.0
         usingSpringWithDamping:0.7
          initialSpringVelocity:0
                        options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
                     animations:^{
                    // Do your stuff here, like changing the frame etc.
                    self.containerView.frame = CGRectMake(0, 100, 300, 300);
    } completion:nil];

非常感谢您的回答,非常棒! - rrphenix

1

代码块启动后将始终运行完毕,并且无法停止(除非您意外使应用崩溃)。您可以考虑使用通知中心或NSTimer手动更改帧。


你也可以设置一个标志来检查,但是在块完成之前会有0.3秒的延迟。 - user850099

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