【问题标题】:CALayer: callback when animation ends?CALayer:动画结束时回调?
【发布时间】:2010-06-14 23:26:16
【问题描述】:

我在同时为多个 CALayers 设置动画时遇到了一些问题,希望有人能指出我正确的方向。

我的应用程序包含一个 CALayer 数组。每一层的位置都设置为(previousLayer.position.y + previousLayer.bounds.height),基本上就像一张桌子一样。然后我有一个方法,每次调用它时,都会在堆栈中添加一个新层并将其 Y 位置设置为 0。然后数组中所有其他层的 Y 位置会偏移新层的高度层(基本上将所有旧层向下推)。

我遇到的问题是在上一个动画完成之前阻止添加新图层。有没有办法判断隐式动画何时完成?或者,如果我使用CABasicAnimation 和animationDidFinish,有没有办法告诉在调用animationDidFinish 时哪个对象完成了动画?

【问题讨论】:

    标签: animation core-animation calayer cabasicanimation


    【解决方案1】:

    您可以为动画对象上的键设置任意值。这意味着您可以将您正在制作动画的图层与动画相关联,然后在 -animationDidStop:finished 中查询它:您可以通过这种方式创建动画:

    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
    // set other fields...
    
    [anim setValue:layerToAnimate forKey:@"layer"];
    
    // Start the animation
    [layerToAnimate addAnimation:anim forKey:nil];
    

    然后在动画停止时检查该值:

    - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
    {
        CALayer *animatedLayer = [animation valueForKey:@"layer"];
        // do something with the layer based on some condition...
        // spin off the next animation...
    
        [CATransaction begin];
        [CATransaction setValue:(id)kCFBooleanTrue
                     forKey:kCATransactionDisableActions];
        [animatedLayer setPosition:position];
        [CATransaction commit];
    }
    

    这是显式动画,但它应该可以满足您的需求。

    【讨论】:

    • 这很奏效。代码被调用,我可以从键中取回图层对象。但是当我尝试将 layer.position 设置为动画结束时图层应该位于的位置时,我遇到了闪烁效果。看起来动画结束了,图层位置在我的 'layer.position =' 被调用之前被设置回原点位置。知道如何解决这个问题吗?
    • 是的。如果要在动画结束时设置位置属性,则必须在 -animationDidStop:finished: 方法的事务中禁用隐式动画。我将使用相关代码更新我的答案。
    • 您发布的代码与我的相同,并导致闪烁。我只是想出了如何解决它,并将在几秒钟内发布代码。感谢您的所有帮助!
    • 为我工作,但我不得不把它放在 animationDidStart 中
    【解决方案2】:

    您可以尝试用CATransaction 包围您的代码。这是 Swift 3 中的样子:

    CATransaction.begin()
    CATransaction.setCompletionBlock({
      // run after the animations
    })
    // animtations
    CATransaction.commit()
    

    【讨论】:

    • 这是这里最简洁的解决方案,效果非常好。
    【解决方案3】:

    事实证明,我没有将 CABasicAnimation 直接添加到 CALayer 中,而是将其添加到图层的“动作”字典中……这使图层在动画结束后保持在其最终位置,但仍然调用 ' animationDidFinish' 方法。

    -(void)startAnimation {
        if(!animating){
            animating = YES;
            for(int i=0; i<[tweets count]; i++) {
                //get the layer
                CETweetLayer *currentLayer = [tweets objectAtIndex:i];
    
                //setup the orgin and target y coordinates
                float targetY = currentLayer.position.y + offset;
    
            //setup the animation
            CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
            anim.delegate = self;
            currentLayer.actions = [NSDictionary dictionaryWithObject:anim forKey:@"position"];
            currentLayer.position = CGPointMake(self.bounds.size.width/2, targetY);
         }
        }
    }
    

    然后……

    -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        animating = NO; 
    }
    

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 1970-01-01
      • 1970-01-01
      • 2015-09-29
      • 2017-06-07
      • 1970-01-01
      • 2023-04-06
      • 2013-12-15
      相关资源
      最近更新 更多