如何在触发新动画时取消上一个动画?

时间:2015-02-04 09:15:57

标签: ios swift

我正在编写相机应用程序,并且在用户点击屏幕时无法显示焦点方块。

我的代码是(快速):

self.focusView.center = sender.locationInView(self.cameraWrapper)
self.focusView.transform = CGAffineTransformMakeScale(2, 2)
self.focusView.hidden = false

UIView.animateWithDuration(0.5, animations: { [unowned self] () -> Void in
    self.focusView.transform = CGAffineTransformIdentity
}, completion: { (finished) -> Void in
    UIView.animateWithDuration(0.5, delay: 1.0, options: nil, animations: { () -> Void in
        self.focusView.alpha = 0.0
    }, completion: { (finished) -> Void in
            self.focusView.hidden = true
            self.focusView.alpha = 1.0
    })
})

但是,如果在前一个动画没有完成时连续点击屏幕,旧的和新的动画会混淆,焦点视图会表现得很奇怪,例如它会很快消失。

有人能告诉我如何取消之前的动画,尤其是之前的完成块吗?

4 个答案:

答案 0 :(得分:34)

您可以使用方法removeAllAnimations来停止动画 用下面的代码替换你的代码

self.focusView.center = sender.locationInView(self.cameraWrapper)
self.focusView.transform = CGAffineTransformMakeScale(2, 2)
self.focusView.hidden = false
self.focusView.layer.removeAllAnimations() // <<====  Solution
UIView.animateWithDuration(0.5, animations: { [unowned self] () -> Void in
    self.focusView.transform = CGAffineTransformIdentity
}, completion: { (finished) -> Void in

    UIView.animateWithDuration(0.5, delay: 1.0, options: nil, animations: { () -> Void in
        self.focusView.alpha = 0.0
    }, completion: { (finished) -> Void in
            self.focusView.hidden = true
            self.focusView.alpha = 1.0
    })
})


参考:link
enter image description here

答案 1 :(得分:1)

就我而言,我使用addSubview()添加了聚焦指标。

self.view.addSubview(square)

square是我在函数中定义的UIView。因此,当用户点击屏幕进行聚焦时,此功能将在子视图上添加一个正方形。 并且当下一次点击发生时取消这个动画,我只是简单地使用removeFromSuperview()函数,当这个函数调用它时,它的superview中删除了视图,这是聚焦方块。

filterView.subviews.forEach({ $0.removeFromSuperview() })

与上述删除动画的方法不同,但直接删除了子视图。

答案 2 :(得分:1)

@Jageen解决方案很棒,但是我使用UIStackView动画,因此需要其他步骤。我有内部带有view1和view2的stackView,其中一个视图应该可见而一个隐藏:

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)
}

答案 3 :(得分:0)

在我的情况下,我只需要设置值,我将其设置为具体值。

例如

 if ([indexPath isEqual:self.currentPlayerOrderIndexPath])
    {
        [UIView animateWithDuration:0.5
                              delay:0.0
                            options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseInOut
                         animations:^{
                             cell.avatarImageV.transform = CGAffineTransformMakeScale(1.15,1.15);
                         }
                         completion:NULL];
    }
    else
    {
        cell.avatarImageV.transform = CGAffineTransformMakeScale(1.0, 1.0);