2

I am looking for the way how to draw a hollow circle using Core Graphics (CGContext) in iOS. I tried to do it using the code:

- (void)drawRect:(CGRect)rect {
      [super drawRect:rect];
      CGContextRef ctx = UIGraphicsGetCurrentContext();
      CGContextSetLineWidth(ctx, 8.0);
      CGContextSetStrokeColor(ctx, CGColorGetComponents([[UIColor redColor] CGColor]));
      CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor blueColor] CGColor]));
      CGContextFillEllipseInRect(ctx, rect);
      CGContextFillPath(ctx);
}

but it draws the filled circle. Since this question is over discussed here but other examples like this give me only filled circles.

Community
  • 1
  • 1
Darius Miliauskas
  • 3,391
  • 4
  • 35
  • 53

4 Answers4

5

If you want to draw a circle within the rect, using Stroke methods and the rect in parameter you will draw a part of the cercle outside the rect.

You then have two choices, assuming you know the width of the circle you want to draw.

First, you can stroke the line, but you have to draw it in a smaller rect :

-(void)drawRect:(CGRect)rect {

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGFloat innerWidth = 8;
    [[UIColor redColor] setStroke];

    CGContextSetLineWidth(ctx, innerWidth);

    // We add an ellipsis shifted by half the inner Width
    CGContextAddEllipseInRect(ctx, CGRectInset(rect, innerWidth, innerWidth));

    // Stroke the path
    CGContextStrokePath(ctx);
}

You can also fill the circles using the even-odd rule (Apple docs)

-(void)drawRect:(CGRect)rect {

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGFloat innerWidth = 8;
    [[UIColor redColor] setStroke];

    // Add the outer circle
    CGContextAddEllipseInRect(ctx, rect);
    // Add the inner circle
    CGContextAddEllipseInRect(ctx, CGRectInset(rect, innerWidth, innerWidth));

    // Fill the path using the EO rule
    CGContextEOFillPath(ctx);
}
Michaël Azevedo
  • 3,874
  • 7
  • 31
  • 45
3

If you only want the circle outline, don't fill it.

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

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(ctx, 8.0);
    [[UIColor redColor] set];
    CGContextStrokeEllipseInRect(ctx, rect);
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
2

Use CGContextStrokeEllipseInRect instead of CGContextFillEllipseInRect. And since you haven't built a path in the current context, get rid of CGContextFillPath.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
2

One way you could do it is draw a filled circle and then draw a slightly smaller circle with CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeClear)

After your code add something like

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctx, 5.0);
CGContextSetBlendMode(ctx,kCGBlendModeClear)
CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor blueColor] CGColor]));
CGContextFillEllipseInRect(ctx, rect);
CGContextFillPath(ctx);

UIGraphicsEndImageContext();

I use CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeClear) in my drawing application, which is probably a better use. Stroking the path will probably work for you.

Minebomber
  • 1,209
  • 2
  • 12
  • 35
  • This is a valuable alternative idea because stroking the ellipse will actually draw half the stroke _outside_ the intended circle, whereas filling, insetting, and then filling again will keep the resulting figure entirely contained. However, your code doesn't do what you're talking about. – jscs Nov 24 '15 at 20:53