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

6l7fqoea  于 2023-06-21  发布在  Swift
关注(0)|答案(5)|浏览(147)

我正在写一个相机应用程序,当用户点击屏幕时,我在显示对焦框时遇到了麻烦。
我的代码是(在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
    })
})

但是,如果在前一个动画未完成时连续点击屏幕,则新旧动画将混淆,焦点视图将表现得奇怪,例如它将很快消失。
谁能告诉我如何取消以前的动画,特别是以前的完成块?

llew8vvj

llew8vvj1#

可以使用方法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
    })
})

参考:链接

cwtwac6a

cwtwac6a2#

@Jageen解决方案很棒,但我使用了UIStackView动画,在那里我需要额外的步骤。我有一个stackView,里面有view 1和view 2,一个视图应该是可见的,一个视图应该是隐藏的:

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

bq3bfh9z3#

在我的例子中,我使用addSubview()添加对焦指示器。

self.view.addSubview(square)

square是函数中定义的UIView I。所以当用户点击屏幕聚焦时,这个功能会在子视图上添加一个正方形。为了在下一次点击时取消这个动画,我只是简单地使用removeFromSuperview()函数,当这个函数被调用时,它将视图从它的超视图中删除,这是这里的焦点方块。

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

它与上面的移除动画的方法不同,而是直接移除子视图。

roqulrg3

roqulrg34#

在我的例子中,我只需要设置值,我动画具体的价值。
例如:

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);
smtd7mpg

smtd7mpg5#

extension CALayer {
    func removeAllAnimationsRecursive() {
        removeAllAnimations()
        sublayers?.forEach {
            $0.removeAllAnimationsRecursive()
        }
    }
}

相关问题