Reimplement UIView block based animation methods with custom easing curve

后端 未结 2 1951
时光说笑
时光说笑 2021-02-10 16:08

The lack of custom easing curves in UIView\'s block based animation methods leads to Core Animation if more advanced curves are needed.

A way of doing this with a Categ

相关标签:
2条回答
  • 2021-02-10 16:54

    I don't know how Apple implements their block based methods, but reading BlocksKit sourcecode, I understood that to implement the method you mentioned, you probably need to:

    1. Declare a UIView category such as UIView (block)
    2. In the category, add a NSTimer property to fire/invalidate the timer with given duration
    3. In the category, add a block property to keep the easingCurveFunction block code
    4. In the category, add another block perty to keep the animation block code
    5. In your block-based method, set the timer, save the blocks code to properties
    6. When the timer fires, run the easingCurveFunction block and animation block, as you keep them in the properties

    I actually followed this practice when adding my own block-based methods to Apple's classes.

    0 讨论(0)
  • 2021-02-10 17:10

    I'm not sure about creating a block-based method, but I've found that a fairly simple way to implement a custom easing function and still used block-based animations is to override the layer's addAnimation:(CAAnimation *)anim forKey:(NSString *)key method and swap in a different easing function for whatever view you want to animate.

    To start, subclass 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're returning the custom layer class...

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

    Then, you can use the standard block-based animation methods such as...

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

    ...and the custom easing 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-based animations. Keep in mind, however, that the easing function will apply to any and all animations that are animated through the block-based methods. So if you want to animate the alpha property for example, but don't want to use the custom easing function, you will have to fiddle around with it or maybe come up with a different solution altogether.

    Lastly, an awesome tool for easily creating and testing easing functions can be found here: http://matthewlein.com/ceaser/

    0 讨论(0)
提交回复
热议问题