Question

I am trying to animate a CGColor fillColor property on a CAShapeLayer. I can get it working just fine using Objective-C with the following syntax:

- (void)viewDidLoad {
    [super viewDidLoad];

    // Create the path
    thisPath = CGPathCreateMutable();
    CGPathMoveToPoint(thisPath, NULL, 100.0f, 50.0f);
    CGPathAddLineToPoint(thisPath, NULL, 10.0f, 140.0f);
    CGPathAddLineToPoint(thisPath, NULL, 180.0f, 140.0f);
    CGPathCloseSubpath(thisPath);

    // Create shape layer
    shapeLayer = [CAShapeLayer layer];
    shapeLayer.frame = self.view.bounds;
    shapeLayer.path = thisPath;
    shapeLayer.fillColor = [UIColor redColor].CGColor;

    [self.view.layer addSublayer:shapeLayer];

    // Add the animation
    CABasicAnimation* colorAnimation = [CABasicAnimation animationWithKeyPath:@"fillColor"];
    colorAnimation.duration = 4.0;
    colorAnimation.repeatCount = 1e100f;
    colorAnimation.autoreverses = YES;
    colorAnimation.fromValue = (id) [UIColor redColor].CGColor;
    colorAnimation.toValue = (id) [UIColor blueColor].CGColor;
    [shapeLayer addAnimation:colorAnimation forKey:@"animateColor"];
}

This animates the color shift as expected. When I port this to Monotouch, I tried:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        thisPath = new CGPath();
        thisPath.MoveToPoint(100,50);
        thisPath.AddLineToPoint(10,140);
        thisPath.AddLineToPoint(180,140);
        thisPath.CloseSubpath();

        shapeLayer = new CAShapeLayer();
        shapeLayer.Path = thisPath;
        shapeLayer.FillColor = UIColor.Red.CGColor;

        View.Layer.AddSublayer(shapeLayer);

        CABasicAnimation colorAnimation = CABasicAnimation.FromKeyPath("fillColor");
        colorAnimation.Duration = 4;
        colorAnimation.RepeatCount = float.PositiveInfinity;
        colorAnimation.AutoReverses = true;
        colorAnimation.From = NSObject.FromObject(UIColor.Red.CGColor);
        colorAnimation.To = NSObject.FromObject(UIColor.Blue.CGColor);

        shapeLayer.AddAnimation(colorAnimation, "animateColor");
    }

but the animation never plays. The animationStarted event does get raised, so presumably it is trying to run the animation, but I don't see any visible evidence on the screen.

I've been playing with this for the better part of a day and I think it's the conversion from a CGColor into an NSObject - I've tried NSObject.FromObject, NSValue.ValueFromHandle, etc. but haven't found any way to get the animation to correctly pickup the start and end values.

What is the proper way to supply a CGColor as an NSObject for an animation?

Thanks!

Was it helpful?

Solution

Mark,

You can use

colorAnimation.To = Runtime.GetNSObject (UIColor.Blue.CGColor.Handle);

to get the right object for the animation.

Kudos to https://stackoverflow.com/users/187720/geoff-norton for actually giving me the answer to use Runtime.GetNSObject and to fix this issue.

Hope this helps,

ChrisNTR

OTHER TIPS

It's also possible to do:

colorAnimation.From = NSObject.FromObject (UIColor.Red.CGColor.Handle);

and the next versions of MonoTouch (6.0.8+) will allow:

colorAnimation.From = NSObject.FromObject (UIColor.Red.CGColor);

and the same for CGPath and other INativeObject that are not NSObject.

I've just looked at some similar code written in our app (admittedly CAKeyFrameAnimation rather than CABasicAnimation) and they seem to have wrapped the .AddAnimation() in a UIView animation block. E.g:

UIView.Animate(4, delegate{
    shapeLayer.AddAnimation(colorAnimation, "animateColor");
});

I'm not sure if this is the correct way of doing this, but it seems to work in our app.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top