使用BOOL或完成块停止自动反转/无限重复的UIView动画

29
我正在设置以下 UIView animateWithDuration: 方法,以便在程序的其他地方设置我的 animationOn BOOL 以取消该无限循环重复。 我一直认为每次动画循环结束时都会调用 completion 块,但事实并非如此。
重复动画中是否会调用 completion 块? 如果不是,那么我是否有另一种方法可以在此方法之外停止此动画?
- (void) animateFirst: (UIButton *) button
{
    button.transform = CGAffineTransformMakeScale(1.1, 1.1);
    [UIView animateWithDuration: 0.4
                          delay: 0.0
                        options: UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
                     animations: ^{
                         button.transform = CGAffineTransformIdentity;
                     } completion: ^(BOOL finished){
                         if (!animationOn) {
                             [UIView setAnimationRepeatCount: 0];
                         }
    }];
}
5个回答

56

当动画被中断时,完成块才会被调用。例如,当应用程序通过多任务切换到后台并返回前台时,它将被调用。在这种情况下,动画会停止。您应该在这种情况下重新启动动画。

要停止动画,可以从视图的图层中删除它:

[button.layer removeAllAnimations];

很遗憾,那没有起作用。动画在应用变换后仍在继续。(我将 .transform 设置为 CGAffineTransformMakeScale(1.0,1.0))。 - Luke
我找到了另一种可能有效的方法。我更新了我的答案。你可以试试看吗? - Tom van Zummeren
哦,你自己解决了 :) 不过还是谢谢你接受我的答案。 - Tom van Zummeren
你的出现几乎是在我点击添加按钮的同时,所以我想这意味着你先打的 ;) - Luke
2
@TomvanZummeren 但这将删除每个动画... 如果您有多个动画块,而您只想停止其中一个动画块... - Supertecnoboff

9

虽然有些老旧,但还有另一种选择。

你也可以设置另一个动画,在同一个视图上不重复播放,这样你也可以捕获当前状态并使用选项UIViewAnimationOptionBeginFromCurrentState将其返回到原始状态。同时,你的完成块也会被调用。

-(void)someEventSoStop
{
    button.transform = CGAffineTransformMakeScale(1.0, 1.0);
    [UIView animateWithDuration: 0.4
                          delay: 0.0
                        options: UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState
                     animations: ^{
                         button.transform = CGAffineTransformIdentity;
                     } completion: ^(BOOL finished){

                     }];
}

这种方法比其他解决方案更好,因为它可以平稳地将动画恢复到标识状态。 - Nikolozi

2

我通过调用[button.layer removeAllAnimations]解决了这个问题。


2
我尝试过这个,但对我没有用。你在代码中从哪里调用这个方法? - Supertecnoboff

1
根据View类参考文档:如果您使用了任何类方法,例如animateWithDuration:delay:options:animations:completion:,如果持续时间设置为负值或0,则更改将在不执行动画的情况下进行。因此,我做了以下操作以停止无限动画:
[UIView animateWithDuration:0.0 animations:^{      button.layer.affineTransform = CGAffineTransformIdentity;  }];

我认为这比在建议答案中从层中删除所有动画要好。请注意,这适用于UIView类中的所有其他类动画方法。

这对我没有起作用。我不得不调用removeAllAnimations。 - Mike Taverne

0
调用removeAllAnimations()方法可以起作用。然而,调用此方法会立即停止动画并应用UIView.animate块内的变换,从而导致不流畅的过渡。为了在移除动画时实现平滑过渡,您可以使用UIView.transition方法,它将使用交叉溶解动画平滑地将当前视图状态过渡到最终状态,从而实现平滑过渡。
UIView.transition(with: stackView, duration: 0.3, options: .transitionCrossDissolve) {
    self.button.layer.removeAllAnimations()
    self.button.alpha = 1
}

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