开发者

How to draw a rounded rectangle in Core Graphics / Quartz 2D?

I need to draw 开发者_StackOverflow中文版an outline for a rounded rectangle. I know I can make lines and arcs, but maybe there is also a function for rounded rects?


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.


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); 


 UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:bubbleBounds cornerRadius:15.0];
 CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
 [bezierPath stroke];


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:

How to draw a rounded rectangle in Core Graphics / Quartz 2D?


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


CGPathCreateWithRoundedRect() will do what you want.

CGPathRef CGPathCreateWithRoundedRect(
   CGRect rect,
   CGFloat cornerWidth,
   CGFloat cornerHeight,
   const CGAffineTransform *transform
);

Available starting in iOS 7.0


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)


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;
}


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()
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜