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

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

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

// set view properties

[UIView commitAnimations];

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


当前回答

Use:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];

其他回答

如果你通过改变常量而不是视图属性来动画约束,其他方法在iOS 8上都不起作用。

示例动画:

self.constraint.constant = 0;
[self.view updateConstraintsIfNeeded];
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:^{
                     self.constraint.constant = 1.0f;
                     [self.view layoutIfNeeded];
                 } completion:^(BOOL finished) {

                 }];

解决方案:

您需要从任何受约束更改影响的视图的层及其子层中删除动画。

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}
CALayer * pLayer = self.layer.presentationLayer;
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:0.001 animations:^{
    self.frame = pLayer.frame;
}];

当我使用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)
}

如果你正在寻找灵活的动画,可以根据你的需要开始和停止,使用UIViewPropertyAnimator。

示例代码

let sampleView = UIView()

lazy var animator: UIViewPropertyAnimator = {
    let animator = UIViewPropertyAnimator(duration: 1.2, curve: .easeOut)
    animator.isInterruptible = true
    return animator
}()

// add and your animatable property
animator.addAnimations {
   // what you need to animate add here
   sampleView.alpha = 0
}

// start animation
animator.startAnimation(afterDelay: 0.5)

如果你需要在动画中间停下来。它将在当前状态下停止动画。

// stop animation
if animator.isRunning {
    animator.stopAnimation(true)
}
[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];