测试UIView是否处于动画中间

时间:2011-04-02 23:02:00

标签: ios cocoa-touch uiview core-animation uiviewanimation

有没有办法判断UIView是否在动画中?当我在视图对象移动时打印出来时,我注意到有一个“动画”条目:

search bar should end editing: <UISearchBar: 0x2e6240; frame = (0 0; 320 88); text = ''; autoresize = W+BM; animations = { position=<CABasicAnimation: 0x6a69c40>; bounds=<CABasicAnimation: 0x6a6d4d0>; }; layer = <CALayer: 0x2e6e00>>

当动画停止并且我打印视图时,“动画”条目现在消失了:

search bar should end editing: <UISearchBar: 0x2e6240; frame = (0 0; 320 88); text = ''; autoresize = W+BM; layer = <CALayer: 0x2e6e00>>

10 个答案:

答案 0 :(得分:39)

UIView有一个图层(CALayer)。您可以向其发送animationKeys,它将为您提供一系列键,用于标识附加到图层的动画。我想如果有任何条目,动画正在运行。如果你想深入挖掘,请查看CALayer采用的CAMediaTiming protocol。它提供了有关当前动画的更多信息。

答案 1 :(得分:25)

动画实际上附加到基础核心动画CALayer

所以我认为你可以查看myView.layer.animationKeys

答案 2 :(得分:8)

我不确定问题的背景但我曾试图在开始第二个动画之前发现视图是否是动画以避免跳过。但是,有一个UIView动画选项UIViewAnimationOptionBeginFromCurrentState,如果需要,它将组合动画以提供流畅的外观。从而消除了我需要知道视图是否具有动画效果。

答案 3 :(得分:7)

iOS 9+方法,即使layer.animationKeys不包含密钥也能正常工作:

let isInTheMiddleOfAnimation = UIView.inheritedAnimationDuration > 0

来自文档:

  

如果在UIView中调用,此方法仅返回非零值   动画块。

答案 4 :(得分:5)

动画诀窍有一个障碍。

动画完成后,有时可能会有一些animationKeys挥之不去。

这意味着非动画层可以返回一组animationKeys,即使它实际上并不是动画。

您可以通过将动画的removedOnCompletion属性设置为YES来确保自动删除animationKeys。

e.g。

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"aPath"];
animation.removedOnCompletion = YES;

如果对您应用于图层的所有动画执行此操作,则会确保在图层未设置动画时不存在animationKeys。

答案 5 :(得分:3)

其中一些对我不起作用。原因是这些动画是异步的。

我所做的是定义了一个属性

@property BOOL viewIsAnimating;

在我的动画中

[UIView animateWithDuration:0.25
                 animations:^{
                     viewIsAnimating = YES;
                 } completion:^(BOOL finished) {
                     if (finished) {
                         viewIsAnimating = NO;
                     }
                 }];

答案 6 :(得分:1)

参考问题:UIView center position during animation

我比较视图的框架和layer.presentation()?.框架来检查它是否为动画。如果leftView即将完成,则leftView.layer.presentation()?。框架不等于其框架:

if self.leftView.layer.presentation()?.frame == self.leftView.frame {
   // the animation finished
} else {
   // the animation on the way
}

但是,如果视图在动画期间移动到结束位置,则此方法可能无效。可能需要更多的条件检查。

答案 7 :(得分:1)

您可以使用UIView的layer属性。 CALayer具有一个称为动画关键点的属性,您可以检查其计数是否大于0。

if (view.layer.animationKeys.count) {

  // Animating

}else {

// No

}

在文档中:

-(nullable NSArray<NSString *> *)animationKeys;
  

返回一个数组,其中包含当前所有动画的键*   连接到接收器。数组的顺序与顺序*   将在其中应用动画。

答案 8 :(得分:1)

这里有很多过时的答案。如果在同一视图上正在运行UIView动画,我只是需要阻止它开始,所以我在UIView上创建了一个类别:-

extension UIView {

    var isAnimating: Bool {
        return (self.layer.animationKeys()?.count ?? 0) > 0
    }

}

这样,我可以像这样检查任何视图的动画状态:-

if !myView.isAnimating {
  UIView.animate(withDuration: 0.4) {
    ...
  }
} else {
  // already animating
}

这似乎比使用状态变量跟踪它要脆弱。

答案 9 :(得分:0)