4

如果需要更高级的曲线,UIView 的基于块的动画方法中缺少自定义缓动曲线会导致核心动画。

如何使用 Core Animation 创建自定义缓动函数CAKeyframeAnimation中讨论了使用 Category on 执行此操作的方法?.

为了保持我的代码干净和可维护,我想更进一步,重新实现UIView基于块的方法,并包含一个描述缓动曲线函数的块。结果类别UIView看起来像这样:

+ (void)animateWithDuration:(NSTimeInterval)duration easingCurveFunction:(double(^)(double))function  animations:(void (^)(void))animations;

有谁知道苹果如何实现基于块的动画方法?

4

2 回答 2

6

我不确定是否要创建基于块的方法,但我发现实现自定义缓动函数并仍然使用基于块的动画的一种相当简单的方法是覆盖图层的addAnimation:(CAAnimation *)anim forKey:(NSString *)key方法并换成不同的缓动函数您想要动画的任何视图。

首先,继承 CALayer,并添加以下方法...

// CustomViewLayer.m

#import "CustomViewLayer.h"

@implementation CustomViewLayer

- (void)addAnimation:(CAAnimation *)anim forKey:(NSString *)key
{
    if ([anim isKindOfClass:[CABasicAnimation class]]) {

        // intercept the animation and insert your own easing function
        int x1 = 0.250;
        int y1 = 1.185;
        int x2 = 0.210;
        int y2 = 1.000;
        CAMediaTimingFunction *func = [CAMediaTimingFunction functionWithControlPoints:x1 :y1 :x2 :y2];
        anim.timingFunction = func;    
    }

    [super addAnimation:anim forKey:key];
}

@end

在您的视图子类中,确保您返回自定义图层类...

// CustomView.m

#import "CustomView.h"
#import "CustomViewLayer.h"

@implementation CustomView

+ (Class)layerClass
{
    return [CustomViewLayer class];
}

@end

然后,您可以使用标准的基于块的动画方法,例如...

[UIView animateWithDuration:0.3 animations:^{
    [customView setFrame:newFrame];
}];

...并且将使用自定义缓动功能。它可能无法解决您所有的问题,但它很容易做到,并且仍然允许您使用基于块的动画。但是请记住,缓动函数将适用于通过基于块的方法进行动画处理的所有动画。因此,例如,如果您想为 alpha 属性设置动画,但又不想使用自定义缓动功能,您将不得不摆弄它,或者可能会想出一个完全不同的解决方案。

最后,可以在这里找到一个用于轻松创建和测试缓动函数的很棒的工具:http: //matthewlein.com/ceaser/

于 2013-05-31T02:24:07.803 回答
0

我不知道Apple如何实现他们的基于块的方法,但是阅读BlocksKit源代码,我知道要实现你提到的方法,你可能需要:

  1. 声明一个 UIView 类别,例如 UIView (block)
  2. 在类别中,添加一个 NSTimer 属性以触发/使具有给定持续时间的计时器无效
  3. 在类别中,添加一个块属性以保留 easingCurveFunction 块代码
  4. 在类别中,添加另一个块属性以保留动画块代码
  5. 在基于块的方法中,设置计时器,将块代码保存到属性
  6. 当计时器触发时,运行 easingCurveFunction 块和动画块,因为您将它们保存在属性中

在将我自己的基于块的方法添加到 Apple 的类时,我实际上遵循了这种做法。

于 2012-09-22T15:31:31.910 回答