I want to round every corner of this. I use UIBezierPath to draw and set
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
that doesn't work.
Do I have a convenient way to do it,instead of a sequence of addLineToPoint
and addArcWithCenter
In custom view
- (void)drawRect:(CGRect)rect {
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(100, 100)];
[path addLineToPoint:CGPointMake(150, 100)];
[path addLineToPoint:CGPointMake(150, 150)];
[path addLineToPoint:CGPointMake(200, 150)];
[path addLineToPoint:CGPointMake(200, 200)];
[path addLineToPoint:CGPointMake(250, 200)];
[path addLineToPoint:CGPointMake(250, 250)];
[path addLineToPoint:CGPointMake(100, 250)];
[path closePath];
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetFillColorWithColor(context, UIColor.greenColor.CGColor);
CGContextAddPath(context, path.CGPath);
CGContextFillPath(context);
CGContextRestoreGState(context);
}
In Viewcontroller
- (void)viewDidLoad {
[super viewDidLoad];
testvvv *test = [[testvvv alloc] initWithFrame:self.view.bounds];
[self.view addSubview:test];
}
I guess you want this:
There are Core Graphics functions for rounding corners that are not available on UIBezierPath
. They are CGContextAddArcToPoint
and CGPathAddArcToPoint
. I'll explain how they work.
First let's consider how you draw two lines meeting at a sharp corner. When the path is first initialized, its “current point” is at the origin:
You use CGPathMoveToPoint
to move to the start of the first line at (x0, y0)
:
Then you use CGPathAddLineToPoint
to draw the first line, ending at the corner at (x1, y1)
:
Finally, you use CGPathAddLineToPoint
again to draw the second line to (x2, y2)
:
Now let's use CGPathAddArcToPoint
to round the corner instead. Rewind to just after you used CGPathMoveToPoint
to move to the start of the first line:
CGPathAddArcToPoint
takes two points: the point at the corner (which won't be reached since it will round the corner) and the next point in the shape after the corner. So you pass it both (x1,y1)
(the corner) and (x2,y2)
(the end of the next line). You also pass it the radius of the corner:
Notice that CGPathAddArcToPoint
draws the first line for you, and draws arc that forms the rounded corner, and leaves the current point at the end of that arc. So you then use CGPathAddLineToPoint
to draw the second line:
Okay, that explains (I hope) how CGPathAddArcToPoint
works. CGContextAddArcToPoint
works the same way, but operates on the context's path.
To apply this to your staircase shape, you want to use an CG*AddArcToPoint
function to draw every corner. Since you have a closed shape and you want no sharp corners, you don't need to use CG*AddLineToPoint
at all. You can use the arc function to draw every line as well as the rounded corners.
One thing to be careful of is where you start the shape. You can't start at a corner, because then you'd get a straight line out of the corner. Instead, it's easiest to start at the midpoint of one of the lines, far from any corner.
Also, since you're doing this in drawRect:
, you can just use the context's path instead of creating a separate UIBezierPath
or CGPath
object. Here's the code I used to draw the result above:
- (void)drawRect:(CGRect)rect {
CGPoint p[] = {
{100, 100},
{150, 100},
{150, 150},
{200, 150},
{200, 200},
{250, 200},
{250, 250},
{100, 250},
};
size_t count = (sizeof p) / (sizeof p[0]);
CGPoint pLast = p[count - 1];
CGContextRef gc = UIGraphicsGetCurrentContext();
// Start at the midpoint of one of the lines.
CGContextMoveToPoint(gc, 0.5 * (pLast.x + p[0].x), 0.5 * (pLast.y + p[0].y));
for (size_t i = 1; i < count; ++i) {
CGContextAddArcToPoint(gc, p[i-1].x, p[i-1].y, p[i].x, p[i].y, 10);
}
CGContextAddArcToPoint(gc, pLast.x, pLast.y, p[0].x, p[0].y, 10);
// Connect the last corner's arc to the starting point.
CGContextClosePath(gc);
[UIColor.greenColor setFill];
CGContextFillPath(gc);
}