1

I want to achieve the shape shown in image using UIBezier Path, and too the shape is filled with blocks in image it shows one block is filled, how to achieve this.

enter image description here

I have tried the following code taken from here

UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, 10)];
[path addQuadCurveToPoint:CGPointMake(200, 10) controlPoint:CGPointMake(100, 5)];
[path addLineToPoint:CGPointMake(200, 0)];
[path addLineToPoint:CGPointMake(0, 0)];
[path closePath];

Thanks.

Community
  • 1
  • 1
iphonic
  • 12,615
  • 7
  • 60
  • 107
  • So the question is how to make a `UIBezierPath` with one part of it filled, and another part of it just stroked? You can make two shapes instead, of make a shape that would fake the stroke by filling a narrow area. – Vadim Yelagin Oct 02 '13 at 11:27
  • @VadimYelagin that sounds good, I can try making two different drawing and combine them both, but I am not able to get the exact design, can you help me with some code sample? Thanks. – iphonic Oct 02 '13 at 11:35
  • 1
    Looks like you need to use `addArcWithCenter:radius:startAngle:endAngle:clockwise:` instead of quad curves. – Vadim Yelagin Oct 02 '13 at 11:39

1 Answers1

5

It looks to me like both the outline and also each block has the same shape. What you would probably do is to make one shape for the outline, and stroke it, and one shape for each cell and fill it.

Creating the shape

Each shape could be created something like this (as I've previously explained in this answer). It's done by stroking one path (the orange arc) which is a simple arc from one angle to another to get another path (the dashed outline)

Path to be stroked

Before we can stroke the path we to create it. CGPath's work just like UIBezierPath but with a C API. First we move to the start point, then we add an arc around the center from the one angle to another angle.

CGMutablePathRef arc = CGPathCreateMutable();
CGPathMoveToPoint(arc, NULL,
                  startPoint.x, startPoint.y);
CGPathAddArc(arc, NULL,
             centerPoint.x, centerPoint.y,
             radius,
             startAngle,
             endAngle,
             YES);

Now that we have the centered arc, we can create one shape path by stroking it with a certain width. The resulting path is going to have the two straight lines (because we specify the "butt" line cap style) and the two arcs (inner and outer). As you saw in the image above, the stroke happens from the center an equal distance inwards and outwards.

CGFloat lineWidth = 10.0;
CGPathRef strokedArc =
    CGPathCreateCopyByStrokingPath(arc, NULL,
                                   lineWidth,
                                   kCGLineCapButt,
                                   kCGLineJoinMiter, // the default
                                   10); // 10 is default miter limit

You would do this a couple of times to create one path for the stroked outline and one path for each cell.

Drawing the shape

Depending on if it's the outline or a cell you would either stroke it or fill it. You can either do this with Core Graphics inside drawRect: or with Core Animation using CAShapeLayers. Choose one and don't between them :)

Core Graphics

When using Core Graphics (inside drawRect:) you get the graphics context, configure the colors on it and then stroke the path. For example, the outline with a gray fill color and a black stroke color would look like this:

I know that your shape is filled white (or maybe it's clear) with a light blue stroke but I already had a gray and black image and I didn't want to create a new one ;)

CGContextRef c = UIGraphicsGetCurrentContext();
CGContextAddPath(c, strokedArc); // the path we created above
CGContextSetFillColorWithColor(c, [UIColor lightGrayColor].CGColor);
CGContextSetStrokeColorWithColor(c, [UIColor blackColor].CGColor);
CGContextDrawPath(c, kCGPathFillStroke); // both fill and stroke

That will put something like this on screen

Filled and stroked shape

Core Animation

The same drawing could be done with a shape layer like this:

CAShapeLayer *outline = [CAShapeLayer layer];
outline.fillColor = [UIColor lightGrayColor].CGColor;
outline.strokeColor = [UIColor blackColor].CGColor;
outline.lineWidth = 1.0;
outline.path = strokedArc; // the path we created above

[self.view.layer addSublayer: outline];
Community
  • 1
  • 1
David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205
  • Wonderful, I can render the CAShapelayer into an UIImage using UIGraphicsRenderer but how can we do it using CGContextDrawPath!? @David Rönnqvist – Reza.Ab Jan 31 '18 at 16:25