Search code examples
ioscore-animationcalayer

How to inherit animation properties while animating CALayer with implicit animation


I am trying to animate a custom property on a CALayer with an implicit animation:

[UIView animateWithDuration:2.0f animations:^{
    self.imageView.myLayer.myProperty = 1;
}]; 

In -actionForKey: method I need to return the animation taking care of interpolating the values. Of course I have to tell somehow the animation how to retrieve the other parameters for the animation (i.e. the duration and the timing function).

- (id<CAAction>)actionForKey:(NSString *)event
{
    if ([event isEqualToString:@"myProperty"])
        {
            CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"myProperty"];
            [anim setFromValue:@(self.myProperty)];
            [anim setKeyPath:@"myProperty"];
            return anim;
        }
        return [super actionForKey:event];
    }
}

Any idea on how to achieve that? I tried looking for the animation in the layer properties but could not find anything interesting. I also have a problem with the layer animating since actionForKey: is called outside of animations.


Solution

  • I reckon that you have a custom layer with you custom property "myProperty" that you added to the backing layer of UIView - according to the Documentation UIView animation blocks does not support the animation of custom layer properties and states the need to use CoreAnimation:

    Changing a view-owned layer is the same as changing the view itself, and any animations you apply to the layer’s properties respect the animation parameters of the current view-based animation block. The same is not true for layers that you create yourself. Custom layer objects ignore view-based animation block parameters and use the default Core Animation parameters instead.

    If you want to customize the animation parameters for layers you create, you must use Core Animation directly.

    Further the documentation sates that UIView supports just a limited set of animatable properties which are:

    • frame
    • bounds
    • center
    • transform
    • alpha
    • backgroundColor
    • contentStretch

    Views support a basic set of animations that cover many common tasks. For example, you can animate changes to properties of views or use transition animations to replace one set of views with another.

    Table 4-1 lists the animatable properties—the properties that have built-in animation support—of the UIView class.

    https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/AnimatingViews/AnimatingViews.html#//apple_ref/doc/uid/TP40009503-CH6-SW12

    You have to create a CABasicAnimation for that.

    You can have sort of a workaround with CATransactions if you return a CABasicAnimation in actionForKey: like that

    [UIView animateWithDuration:duration animations:^{
        [CATransaction begin];
        [CATransaction setAnimationDuration:duration];
    
        customLayer.myProperty = 1000; //whatever your property takes
    
        [CATransaction commit];
      }];
    

    Just change your actionForKey: method to something like that

    - (id<CAAction>)actionForKey:(NSString *)event
    {
        if ([event isEqualToString:@"myProperty"])
        {
            return [CABasicAnimation animationWithKeyPath:event];
        }
        return [super actionForKey:event];
     }
    

    There is something in Github in case you wan't to have a look: https://github.com/iMartinKiss/UIView-AnimatedProperty