【问题标题】:How to cancel previous animation when a new one is triggered?触发新动画时如何取消之前的动画?
【发布时间】:2015-02-04 09:15:56
【问题描述】:

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

我的代码是(快速):

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

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

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

【问题讨论】:

  • 尝试使用成员 BOOL 变量并在动画中基于 yes 和 no 尝试对其进行动画处理
  • 试试 UIView.setAnimationBeginsFromCurrentState(true);在开始动画之前
  • 我相信2018年最好的办法就是使用UIViewPropertyAnimator

标签: ios swift


【解决方案1】:

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

【讨论】:

  • 我试过你的方法,它似乎确实删除了当前的动画,但新的动画运行不正确。我的按钮调用动画。当我点击按钮时,动画开始。当我再次点击它时,我希望动画停止并从头开始。但是,使用您的 remove 方法,它会停止然后运行一些非常短且混乱的动画。知道为什么吗?
  • 确保在完成块中检查finished。如果您对正在进行的任何动画执行removeAllAnimations(),这将是错误的,在这种情况下,您可能希望跳过该完成块中的步骤。
【解决方案2】:

@Jageen 解决方案很棒,但我使用 UIStackView 动画,我需要额外的步骤。我有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)
}

【讨论】:

    【解决方案3】:

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

    self.view.addSubview(square)
    

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

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

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

    【讨论】:

      【解决方案4】:

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

      例如

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

      【讨论】:

        猜你喜欢
        • 2021-10-14
        • 1970-01-01
        • 1970-01-01
        • 2011-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多