是否有可能取消一个UIView动画,而它正在进行中?或者我必须降到CA级别?

例如,我做过这样的事情(可能设置了一个结束动画动作):

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties

// set view properties

[UIView commitAnimations];

但是在动画完成之前,我得到动画结束事件,我想取消它(缩短它)。这可能吗?在谷歌上搜索一下,会发现一些人问了同样的问题,但没有答案——还有一两个人猜测这是不可能的。


当前回答

如果你只是想平稳地暂停/停止动画

self.yourView.layer.speed = 0;

如何暂停一个层树的动画

其他回答

我也有同样的问题;api没有任何东西来取消某些特定的动画。的

+ (void) setAnimationsEnabled:(BOOL)启用

禁用所有动画,因此不为我工作。有两种解决方案:

1)使你的动画对象成为子视图。然后,当你想要取消该视图的动画时,删除该视图或隐藏它。很简单,但是你需要重新创建没有动画的子视图如果你需要保持它在视图中。

2)只重复一个anim,并在需要时创建一个委托选择器重新启动anim,如下所示:

-(void) startAnimation {
NSLog(@"startAnim alpha:%f", self.alpha);
[self setAlpha:1.0];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(pulseAnimationDidStop:finished:context:)];
[self setAlpha:0.1];
[UIView commitAnimations];
}

- (void)pulseAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if(hasFocus) {
    [self startAnimation];
} else {
    self.alpha = 1.0;
}
}

-(void) setHasFocus:(BOOL)_hasFocus {
hasFocus = _hasFocus;
if(hasFocus) {
    [self startAnimation];
}
}

问题2)总是延迟停止动画,因为它完成当前的动画周期。

希望这能有所帮助。

当我使用UIStackView动画时,除了removeAllAnimations()之外,我需要将一些值设置为初始值,因为removeAllAnimations()可以将它们设置为不可预知的状态。我有stackView与view1和view2在里面,一个视图应该是可见的和一个隐藏:

public func configureStackView(hideView1: Bool, hideView2: Bool) {
    let oldHideView1 = view1.isHidden
    let oldHideView2 = view2.isHidden
    view1.layer.removeAllAnimations()
    view2.layer.removeAllAnimations()
    view.layer.removeAllAnimations()
    stackView.layer.removeAllAnimations()
    // after stopping animation the values are unpredictable, so set values to old
    view1.isHidden = oldHideView1 //    <- Solution is here
    view2.isHidden = oldHideView2 //    <- Solution is here

    UIView.animate(withDuration: 0.3,
                   delay: 0.0,
                   usingSpringWithDamping: 0.9,
                   initialSpringVelocity: 1,
                   options: [],
                   animations: {
                    view1.isHidden = hideView1
                    view2.isHidden = hideView2
                    stackView.layoutIfNeeded()
    },
                   completion: nil)
}

没有一个解决方案对我有效。我用这种方式解决了我的问题(我不知道这是否是正确的方式?),因为我在调用这个太快的时候有问题(当以前的动画还没有完成的时候)。我通过customAnim块传递我想要的动画。

extension UIView
{

    func niceCustomTranstion(
        duration: CGFloat = 0.3,
        options: UIView.AnimationOptions = .transitionCrossDissolve,
        customAnim: @escaping () -> Void
        )
    {
        UIView.transition(
            with: self,
            duration: TimeInterval(duration),
            options: options,
            animations: {
                customAnim()
        },
            completion: { (finished) in
                if !finished
                {
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    // NOTE: This fixes possible flickering ON FAST TAPPINGS
                    self.layer.removeAllAnimations()
                    customAnim()
                }
        })

    }

}

要取消一个动画,你只需要设置当前正在动画的属性,在UIView动画之外。那会停止动画,不管它在哪里,UIView会跳转到你刚刚定义的设置。

以上这些方法都不能解决我的问题,但是这个方法有帮助:UIView动画会立即设置属性,然后将其动画化。当表示层与模型(set属性)匹配时,它会停止动画。

我解决了我的问题,那就是“我想从你出现的地方动画”(“你”指的是视图)。如果你想要那样,那么:

添加QuartzCore。 CALayer * pLayer = theView.layer.presentationLayer;

将位置设置为表示层

我使用了一些选项,包括UIViewAnimationOptionOverrideInheritedDuration

但由于苹果的文档是模糊的,我不知道它是否真的覆盖其他动画时使用,或只是重置计时器。

[UIView animateWithDuration:blah... 
                    options: UIViewAnimationOptionBeginFromCurrentState ... 
                    animations: ^ {
                                   theView.center = CGPointMake( pLayer.position.x + YOUR_ANIMATION_OFFSET, pLayer.position.y + ANOTHER_ANIMATION_OFFSET);
                   //this only works for translating, but you get the idea if you wanna flip and scale it. 
                   } completion: ^(BOOL complete) {}];

现在这应该是一个不错的解决方案。