4

我有一个组动画,但我无法检测到何时点击 animationDidStop。我的代码示例:

[group setDelegate:self];
[view.layer addAnimation:group forKey:@"groupAnimation"];

你们中的任何人都知道我是如何知道组动画何时完成的吗?

4

3 回答 3

13

您还需要设置 animationName 属性以匹配,并确保您的委托函数已正确定义:

CAAnimationGroup *group = [CAAnimationGroup animation];
group.duration = 2.0f;
group.delegate = self;
[group setValue:@"groupAnimation" forKey:@"animationName"];
[group setAnimations:[NSArray arrayWithObjects:myAnimation, myOtherAnimation, nil]];
[view.layer addAnimation:group forKey:@"groupAnimation"];

. . .

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
{
 if (finished)
 {
  NSString *animationName = [animation valueForKey:@"animationName"];
  if ([animationName isEqualToString:@"groupAnimation"])
  {
   // your groupAnimation has ended
  }
 }
}

请注意,对于组动画,在组件动画上设置的代理将被忽略。

于 2012-08-28T20:11:46.927 回答
2

我想出了一种组织动画完成代码的方法,效果非常好。首先,我为动画完成时运行的代码块定义了一个自定义类型:

typedef void (^animationCompletionBlock)(void);

我定义了一个常量,用于将自定义键值对添加到我的动画中:

#define kAnimationCompletionBlock @"animationCompletionBlock"

然后,当我创建动画时,如果我希望它在完成时执行一段代码,我会在我的动画中添加一个自定义属性,其中包含我想要执行的代码块:

animationCompletionBlock theBlock;
theBlock = ^void(void)
{    
  someButton.enabled = TRUE;
  NSLog(@"Animation complete");
  //whatever other code you want to do on completion
}

[myAnimation setValue: theBlock forKey: kAnimationCompletionBlock];

我将视图控制器设置为动画的委托:

myAnimation.delegate = self

最后,我编写了一个通用的动画完成方法,它会查找附加到动画的动画完成块,如果找到就执行它:

/*
 This method looks for a value added to the animation that just completed 
 with the key kAnimationCompletionBlock.
 If it exists, it assumes it is a code block of type animationCompletionBlock, 
 and executes the code block.
 This allows you to add a custom block of completion code to any animation or 
 animation group, rather than Having a big complicated switch statement in your 
 animationDidStop:finished: method with global animation ompletion code.
 (Note that the system won't call the animationDidStop:finished method for 
 individual  animations in an animation group - it will only call the 
 completion method for the entire group. Thus, if you want to run code after 
 part of an animation group  completes, you have to set up a manual timer.)
*/

- (void)animationDidStop:(CAAnimation *)theAnimation 
  finished:(BOOL)flag
{
  animationCompletionBlock theBlock = 
    [theAnimation valueForKey: kAnimationCompletionBlock];
  if (theBlock)
    theBlock();
}

除了非常干净之外,这种方法还允许您的动画完成代码访问您定义块的范围内的局部变量。这解决了将信息传递给您的完成方法的问题,这可能很困难。

您可以在我发布到 Github 的一个工作示例程序中看到这种技术:

Github 上的 Core Animation 演示,包括完成块代码

于 2012-09-07T02:01:06.197 回答
2

我正在使用这个类别来设置完成,如下所示:

[group setCompletionBlock:^{

}];

第一个 CAAnimationGroup+Blocks.h:

#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>

typedef void (^TIFAnimationGroupCompletionBlock)();

@interface CAAnimationGroup (Blocks)

- (void)setCompletionBlock:(TIFAnimationGroupCompletionBlock)handler;

@end

和 CAAnimationGroup+Blocks.m:

#import "CAAnimationGroup+Blocks.h"

static char CAAnimationGroupBlockKey;

@implementation CAAnimationGroup (Blocks)

- (void)setCompletionBlock:(TIFAnimationGroupCompletionBlock)handler {
    objc_setAssociatedObject(self, &CAAnimationGroupBlockKey, handler, OBJC_ASSOCIATION_COPY_NONATOMIC);

    self.delegate = self;
}

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
{
    if (finished)
    {
        TIFAnimationGroupCompletionBlock handler = (TIFAnimationGroupCompletionBlock)objc_getAssociatedObject(self, &CAAnimationGroupBlockKey);
        if (handler) {
            handler();
        }
    }
}

@end
于 2015-01-20T17:48:09.173 回答