I need to draw an outline for a rounded rectangle. I know I can make lines and arcs, but maybe there is also a function for rounded rects?
-
example code http://stackoverflow.com/a/19142851/294884 – Fattie May 14 '14 at 12:09
9 Answers
Instead of making your own path out of lines and arcs, you can use
[UIBezierPath bezierPathWithRoundedRect:cornerRadius:]
or
[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:]
(the second one lets you specify which corners are rounded)
Available in iOS 3.2 or later.

- 7,614
- 3
- 17
- 12
-
7Don't forget to properly inset the rectangle when stroking even if your line width is only one pixel: `CGRectInset(rect, lineWidth, lineWidth)` – pottedmeat Mar 01 '12 at 01:23
-
21Just for completeness, it's also helpful to show what you do with that: ```objc [[UIColor lightGrayColor] setFill]; // set rounded rect's bg color UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect: _yourDrawingFrame cornerRadius: 4]; [roundedRect fillWithBlendMode: kCGBlendModeNormal alpha:1.0f]; ``` – horseshoe7 Aug 12 '12 at 18:28
-
9Actually when stroking I believe the rect should only be inset by half the lineWidth i.e. `CGRectInset(rect, lineWidth/2.0, lineWidth/2.0)`. This is because "the drawn line is centered on the path with its sides parallel to the path segment" (cf. `-[UIBezierPath strokeWithBlendMode:alpha:]`) – Taum Dec 05 '12 at 21:40
-
You can also use `CGPathAddRoundedRect` if you're more into CoreGraphics approaches and supporting iOS 7.0 and on only. – David Berry May 01 '14 at 19:46
There is no prepackaged way to this, you must combine arcs in order to do this, apples quartzdemo project shows the code to do this, here is a reference Quartz Demo and here is the code they provide
// As a bonus, we'll combine arcs to create a round rectangle!
// Drawing with a white stroke color
CGContextRef context=UIGraphicsGetCurrentContext()
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
// If you were making this as a routine, you would probably accept a rectangle
// that defines its bounds, and a radius reflecting the "rounded-ness" of the rectangle.
CGRect rrect = CGRectMake(210.0, 90.0, 60.0, 60.0);
CGFloat radius = 10.0;
// NOTE: At this point you may want to verify that your radius is no more than half
// the width and height of your rectangle, as this technique degenerates for those cases.
// In order to draw a rounded rectangle, we will take advantage of the fact that
// CGContextAddArcToPoint will draw straight lines past the start and end of the arc
// in order to create the path from the current position and the destination position.
// In order to create the 4 arcs correctly, we need to know the min, mid and max positions
// on the x and y lengths of the given rectangle.
CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect);
CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect);
// Next, we will go around the rectangle in the order given by the figure below.
// minx midx maxx
// miny 2 3 4
// midy 1 9 5
// maxy 8 7 6
// Which gives us a coincident start and end point, which is incidental to this technique, but still doesn't
// form a closed path, so we still need to close the path to connect the ends correctly.
// Thus we start by moving to point 1, then adding arcs through each pair of points that follows.
// You could use a similar tecgnique to create any shape with rounded corners.
// Start at 1
CGContextMoveToPoint(context, minx, midy);
// Add an arc through 2 to 3
CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
// Add an arc through 4 to 5
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
// Add an arc through 6 to 7
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
// Add an arc through 8 to 9
CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
// Close the path
CGContextClosePath(context);
// Fill & stroke the path
CGContextDrawPath(context, kCGPathFillStroke);

- 12,494
- 5
- 50
- 73

- 22,363
- 9
- 64
- 71
-
3If anyone is wondering how `CGContextAddArcToPoint()` works, [this](http://stackoverflow.com/a/18992153/1338292) is a pretty good explanation. – Ja͢ck Dec 30 '14 at 08:45
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:bubbleBounds cornerRadius:15.0];
CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
[bezierPath stroke];

- 6,177
- 1
- 35
- 40
Here is a function I wrote that rounds the input rect using a corner radius.
CGMutablePathRef createRoundedCornerPath(CGRect rect, CGFloat cornerRadius) {
// create a mutable path
CGMutablePathRef path = CGPathCreateMutable();
// get the 4 corners of the rect
CGPoint topLeft = CGPointMake(rect.origin.x, rect.origin.y);
CGPoint topRight = CGPointMake(rect.origin.x + rect.size.width, rect.origin.y);
CGPoint bottomRight = CGPointMake(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
CGPoint bottomLeft = CGPointMake(rect.origin.x, rect.origin.y + rect.size.height);
// move to top left
CGPathMoveToPoint(path, NULL, topLeft.x + cornerRadius, topLeft.y);
// add top line
CGPathAddLineToPoint(path, NULL, topRight.x - cornerRadius, topRight.y);
// add top right curve
CGPathAddQuadCurveToPoint(path, NULL, topRight.x, topRight.y, topRight.x, topRight.y + cornerRadius);
// add right line
CGPathAddLineToPoint(path, NULL, bottomRight.x, bottomRight.y - cornerRadius);
// add bottom right curve
CGPathAddQuadCurveToPoint(path, NULL, bottomRight.x, bottomRight.y, bottomRight.x - cornerRadius, bottomRight.y);
// add bottom line
CGPathAddLineToPoint(path, NULL, bottomLeft.x + cornerRadius, bottomLeft.y);
// add bottom left curve
CGPathAddQuadCurveToPoint(path, NULL, bottomLeft.x, bottomLeft.y, bottomLeft.x, bottomLeft.y - cornerRadius);
// add left line
CGPathAddLineToPoint(path, NULL, topLeft.x, topLeft.y + cornerRadius);
// add top left curve
CGPathAddQuadCurveToPoint(path, NULL, topLeft.x, topLeft.y, topLeft.x + cornerRadius, topLeft.y);
// return the path
return path;
}
How to use the function, assuming you subclass UIView and override drawRect:
- (void)drawRect:(CGRect)rect {
// constants
const CGFloat outlineStrokeWidth = 20.0f;
const CGFloat outlineCornerRadius = 15.0f;
const CGColorRef whiteColor = [[UIColor whiteColor] CGColor];
const CGColorRef redColor = [[UIColor redColor] CGColor];
// get the context
CGContextRef context = UIGraphicsGetCurrentContext();
// set the background color to white
CGContextSetFillColorWithColor(context, whiteColor);
CGContextFillRect(context, rect);
// inset the rect because half of the stroke applied to this path will be on the outside
CGRect insetRect = CGRectInset(rect, outlineStrokeWidth/2.0f, outlineStrokeWidth/2.0f);
// get our rounded rect as a path
CGMutablePathRef path = createRoundedCornerPath(insetRect, outlineCornerRadius);
// add the path to the context
CGContextAddPath(context, path);
// set the stroke params
CGContextSetStrokeColorWithColor(context, redColor);
CGContextSetLineWidth(context, outlineStrokeWidth);
// draw the path
CGContextDrawPath(context, kCGPathStroke);
// release the path
CGPathRelease(path);
}
Example output:

- 954
- 13
- 29
-
1Go ahead and use the built-in functions. I made this for learning purposes only. – Erik Villegas May 14 '14 at 17:38
-
This doesn't work : CGMutablePathRef path = createRoundedCornerPath(insetRect, outlineCornerRadius); – datWooWoo Sep 17 '14 at 15:02
-
Make sure you've copied the implementation for the createRoundedCornerPath() function included in my response. It also has to be put above the drawRect: method since it's a C function. – Erik Villegas Sep 17 '14 at 16:49
-
Have a look at BezierPath. Makes it much easier to draw thinks like this – Carmen Nov 23 '14 at 16:07
If you want To have rounded corners on any UIView (or subclass) the easy way is to set the cornerRadius property on the view's layer. See Preview rounded image in iphone
-
4This is by far the easiest. view.layer.cornerRadius = 10.0f. Make sure you import the Quartz framework. – james_womack May 14 '10 at 21:50
CGPathCreateWithRoundedRect()
will do what you want.
CGPathRef CGPathCreateWithRoundedRect(
CGRect rect,
CGFloat cornerWidth,
CGFloat cornerHeight,
const CGAffineTransform *transform
);
Available starting in iOS 7.0

- 619
- 5
- 15

- 543
- 8
- 9
-
3I'm pretty sure this DOES NOT GIVE YOU the new iOS7 rounded corners. Use bezierPathWithRoundedRect for the new iOS7 rounded corners... – Fattie May 14 '14 at 11:47
-
@JoeBlow Not sure what you mean by that, this function was added only in iOS7 and gives you rounded corners; is there another rounded corners? – Ja͢ck Dec 27 '14 at 04:13
Swift:
let rect: CGRect = ...
let path = UIBezierPath(roundedRect: rect, cornerRadius: 5.0)
context.addPath(path.cgPath)
context.setStrokeColor(UIColor.clear.cgColor)
context.drawPath(using: .fillStroke)

- 16,130
- 5
- 49
- 43

- 7,904
- 1
- 47
- 44
Maybe... three? years late, but these days I'm using this without issues.
@import CoreGraphics;
@interface YourViewController ()
@property (weak, nonatomic) IBOutlet UIButton *theButton;
@end
- (void)viewDidLoad
{
[super viewDidLoad];
self.theButton.layer.cornerRadius = 5.0f;
self.theButton.layer.masksToBounds = YES;
// Another useful ones
// Scaling the view (width, height)
self.theButton.transform = CGAfflineTransformMakeScale(1.50f, 1.50f);
// Setting an alpha value (transparency) - nice with Activity Indicator subviews
self.theButton.alpha = 0.8f;
}

- 3,969
- 1
- 21
- 30
Swift 4.2
let lineWidth: CGFloat = 5.0
let path = UIBezierPath(roundedRect: rect.insetBy(dx: lineWidth/2.0, dy: lineWidth/2.0), cornerRadius: 10。0)
path.lineWidth = lineWidth
UIColor.green.setStroke()
path.stroke()

- 2,995
- 3
- 28
- 41

- 15,423
- 11
- 100
- 121