Implement animation methods based on UIView blocks with a custom attenuation curve

The lack of custom attenuation curves in UIView block-based animation methods leads to Core Animation if more complex curves are needed.

The way to do this with a category on CAKeyframeAnimation discussed in How to create a custom attenuation function using Core Animation? .

In order for my code to be clean and maintained, I would like to take one more step and repeat the implementation of the block methods of the UIView and include a block that describes the function of the attenuation curve. the resulting category on a UIView will look something like this:

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

Does anyone have an idea how apple implements its block-based animation methods?

+4
source share
2 answers

I'm not sure about creating a block method, but I found that a fairly simple way to implement a custom easing function and still use block-based animation is to override the addAnimation:(CAAnimation *)anim forKey:(NSString *)key method and swap to another attenuation functions for any kind you want to revive.

To run a subclass of CALayer and add the following method ...

 // 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 

In your view subclass, make sure you return your own class class ...

 // CustomView.m #import "CustomView.h" #import "CustomViewLayer.h" @implementation CustomView + (Class)layerClass { return [CustomViewLayer class]; } @end 

Then you can use standard block-based animation techniques such as ...

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

... and the user attenuation function will be used. It may not solve all your problems, but it is easy to do, and it still allows you to use block animations. However, keep in mind that the easing function will apply to all animations that are animated using block-based labels. Therefore, if you want to animate an alpha property, for example, but don’t want to use a custom easing function, you will have to play with it or even come up with a different solution.

Finally, here you can find a terrific tool to easily create and test attenuation functions: http://matthewlein.com/ceaser/

+5
source

I don’t know how Apple implements its block methods, but, reading BlocksKit sourcecode, I realized that to implement the method you probably should:

  • Declare a UIView category such as UIView (block)
  • In the category, add the NSTimer property to start / cancel the timer with the specified duration
  • In the category, add a block property to save the easingCurveFunction block code
  • In the category, add another block to save the animation block code
  • In the block-based method, set the timer, save the block code to Properties
  • When the timer fires, run the easingCurveFunction block and the animation block as you save them in the properties

I really stuck with this practice by adding my own block methods to Apple classes.

0
source

Source: https://habr.com/ru/post/1211006/


All Articles