6
votes

I'm trying to create a circular loading bar and want to use Core Graphics instead of masking images to create the effect. However, I'm not getting the fidelity that I was hoping for:enter image description here

No matter what have I've tried, the jaggies seem pretty bad. Antialiasing is on and I've already tried turning the "flatness" down to .1 on the CGContextRef. The image is from the (Retina) simulator, it looks slightly better on a device but still isn't that great.

Drawing code, within a subclass of CALayer:

-(void)drawInContext:(CGContextRef)ctx {    
    CGPoint center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);

    CGFloat delta = toRadians(360 * percent);

    CGFloat innerRadius = 69.5;
    CGFloat outerRadius = innerRadius + 12;

    CGContextSetFillColorWithColor(ctx, [UIColor colorWithRed:99/256.0 green:183/256.0 blue:70/256.0 alpha:.5].CGColor);
    CGContextSetStrokeColorWithColor(ctx, [UIColor colorWithRed:99/256.0 green:183/256.0 blue:70/256.0 alpha:10.0].CGColor);
    CGContextSetLineWidth(ctx, 1);

    CGMutablePathRef path = CGPathCreateMutable();

    CGPathAddRelativeArc(path, NULL, center.x, center.y, innerRadius, -(M_PI / 2), delta);
    CGPathAddRelativeArc(path, NULL, center.x, center.y, outerRadius, delta - (M_PI / 2), -delta);
    CGPathAddLineToPoint(path, NULL, center.x, center.y-innerRadius);

    CGContextAddPath(ctx, path);
    CGContextFillPath(ctx);
    CGContextAddPath(ctx, path);
    CGContextStrokePath(ctx);
}

Is this the best Core Graphics can do or am I missing something?

1
Considering that your image has clearly been scaled by 2 in each dimension, and you took the image from the Retina simulator, I would say there's a problem with the transform of your layer, or one of its parents. Are you creating ctx in some other method or is the framework passing it to you? What is the output of NSLog("%@", [[[UIApplication sharedApplication] keyWindow] recursiveDescription])?rob mayoff
The context is given to me by the CALayer. Here is the output of the recursiveDescription. KDGoalBar is the UIControl subclass this is being placed in and KDGoalBarPercentLayer is where the actual drawing is being done.Kevin

1 Answers

11
votes

Found out my specific problem. Since I was creating a CALayer (to add as a sublayer) the contentScale was not automatically getting set to a Retina display. This solves it:

percentLayer.contentsScale = [UIScreen mainScreen].scale;

Thanks Rob, for pushing me in the right direction.