Search code examples
iphoneiosuiviewcore-animation

Create a custom animatable property


On UIView you can change the backgroundColour animated. And on a UISlideView you can change the value animated.

Can you add a custom property to your own UIView subclass so that it can be animated?

If I have a CGPath within my UIView then I can animate the drawing of it by changing the percentage drawn of the path.

Can I encapsulate that animation into the subclass.

i.e. I have a UIView with a CGPath that creates a circle.

If the circle is not there it represents 0%. If the circle is full it represents 100%. I can draw any value by changing the percentage drawn of the path. I can also animate the change (within the UIView subclass) by animating the percentage of the CGPath and redrawing the path.

Can I set some property (i.e. percentage) on the UIView so that I can stick the change into a UIView animateWithDuration block and it animate the change of the percentage of the path?

I hope I have explained what I would like to do well.

Essentially, all I want to do is something like...

[UIView animateWithDuration:1.0
 animations:^{
     myCircleView.percentage = 0.7;
 }
 completion:nil];

and the circle path animate to the given percentage.


Solution

  • If you extend CALayer and implement your custom

    - (void) drawInContext:(CGContextRef) context
    

    You can make an animatable property by overriding needsDisplayForKey (in your custom CALayer class) like this:

    + (BOOL) needsDisplayForKey:(NSString *) key {
        if ([key isEqualToString:@"percentage"]) {
            return YES;
        }
        return [super needsDisplayForKey:key];
    }
    

    Of course, you also need to have a @property called percentage. From now on you can animate the percentage property using core animation. I did not check whether it works using the [UIView animateWithDuration...] call as well. It might work. But this worked for me:

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"percentage"];
    animation.duration = 1.0;
    animation.fromValue = [NSNumber numberWithDouble:0];
    animation.toValue = [NSNumber numberWithDouble:100];
    
    [myCustomLayer addAnimation:animation forKey:@"animatePercentage"];
    

    Oh and to use yourCustomLayer with myCircleView, do this:

    [myCircleView.layer addSublayer:myCustomLayer];