Why when I add my animation with Core Animation does it immediately snap back to what it was at the end? [duplicate]

StackOverflow https://stackoverflow.com/questions/22444678

Question

I'm trying to build a simple pie-chart style progress indicator. It animates well, but after the animation concludes, it snaps right back to the previous value before the animation.

My code is as follows:

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    // Create a white ring that fills the entire frame and is 2 points wide.
    // Its frame is inset 1 point to fit for the 2 point stroke width
    CGFloat radius = CGRectGetWidth(self.frame) / 2;
    CGFloat inset  = 1;
    CAShapeLayer *ring = [CAShapeLayer layer];
    ring.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)
                                           cornerRadius:radius-inset].CGPath;

    ring.fillColor   = [UIColor clearColor].CGColor;
    ring.strokeColor = [UIColor whiteColor].CGColor;
    ring.lineWidth   = 2;

    // Create a white pie-chart-like shape inside the white ring (above).
    // The outside of the shape should be inside the ring, therefore the
    // frame needs to be inset radius/2 (for its outside to be on
    // the outside of the ring) + 2 (to be 2 points in).
    self.innerPie = [CAShapeLayer layer];
    inset = radius/2; // The inset is updated here
    self.innerPie.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)
                                               cornerRadius:radius-inset].CGPath;
    self.innerPie.fillColor   = [UIColor clearColor].CGColor;
    self.innerPie.strokeColor = [UIColor whiteColor].CGColor;
    self.innerPie.lineWidth   = (radius-inset)*2;

    [self.layer addSublayer:ring];
    [self.layer addSublayer:self.innerPie];

    self.progress = 0.0;
    self.innerPie.hidden = YES;
}

- (void)setProgress:(CGFloat)progress animated:(BOOL)animated {
    self.innerPie.hidden = NO;

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    pathAnimation.duration = 3.0;
    pathAnimation.fromValue = [NSNumber numberWithFloat:_progress];
    pathAnimation.toValue = [NSNumber numberWithFloat:progress];
    [self.innerPie addAnimation:pathAnimation forKey:@"strokeEndAnimation"];

    if (_progress != progress) {
        _progress = progress;
    }
}

I simply set it up in drawRect then have a method to set the progress with an animation. What am I doing wrong here?

Was it helpful?

Solution

That's how core Animation works. What you want to do is to set the property to it's final value just before adding the animation to the layer. Then the animation hides the fact that you changed the property, and when the animation is removed after it's finished, the property is at it's end value.

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