Here is an implementation of a CALayer based on CAShapeLayer:
ProgressLayer.h/m
#import <QuartzCore/QuartzCore.h>
@interface ProgressLayer : CAShapeLayer
-(void) computePath:(CGRect)r;
-(void) showProgress;
@end
#import "ProgressLayer.h"
@implementation ProgressLayer
-(id)init {
self=[super init];
if (self) {
self.path = CGPathCreateWithEllipseInRect(CGRectMake(0, 0, 50, 50), 0);
self.strokeColor = [UIColor greenColor].CGColor;
self.lineWidth=40;
self.lineCap = kCALineCapRound;
self.strokeEnd=0.001;
}
return self;
}
-(void) computePath:(CGRect)r {
self.path = CGPathCreateWithEllipseInRect(r, 0);
}
-(void)showProgress {
float advance=0.1;
if (self.strokeEnd>1) self.strokeEnd=0;
CABasicAnimation * swipe = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
swipe.duration=0.25;
swipe.fromValue=[NSNumber numberWithDouble:self.strokeEnd];
swipe.toValue= [NSNumber numberWithDouble:self.strokeEnd + advance];
swipe.fillMode = kCAFillModeForwards;
swipe.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
swipe.removedOnCompletion=NO;
self.strokeEnd = self.strokeEnd + advance;
[self addAnimation:swipe forKey:@"strokeEnd animation"];
}
@end
I used this layer as a backing layer of an UIView:
#import "ProgressView.h"
#import "ProgressLayer.h"
@implementation ProgressView
-(id)initWithCoder:(NSCoder *)aDecoder {
self=[super initWithCoder:aDecoder];
if (self) {
[(ProgressLayer *)self.layer computePath:self.bounds];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
ProgressLayer * l = self.layer;
[l showProgress];
}
- (void)drawRect:(CGRect)rect {
[[UIColor redColor] setStroke];
UIRectFrame(self.bounds);
}
+(Class)layerClass {
return [ProgressLayer class];
}
@end