使用自定义缓动曲线重新实现基于UIView块的动画方法

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

在如何使用Core Animation创建自定义缓动函数中讨论了使用CAKeyframeAnimation上的类别执行此操作的方法? 。

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

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

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

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

首先,inheritanceCA​​Layer,并添加以下方法……

 // 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]; }]; 

…将使用自定义缓动function。 它可能无法解决您的所有问题,但它很容易做到,它仍然允许您使用基于块的动画。 但请记住,缓动function将适用于通过基于块的方法设置动画的任何和所有动画。 因此,如果您想要为alpha属性设置动画,例如,但又不想使用自定义缓动function,则必须使用它或者可能完全提出不同的解决方案。

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

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

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

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