如何在Core Graphics / Quartz 2D中绘制圆角矩形?

时间:2021-09-13 13:34:32

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?

我需要画一个圆形矩形的轮廓。我知道我可以画线和弧,但也许还有一个圆矩形的函数?

8 个解决方案

#1


123  

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.

在iOS 3.2或更高版本中可用。

#2


56  

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

没有预先打包的方法,你必须合并弧才能做到这一点,apple quartzdemo项目展示了做这个的代码,这是一个引用Quartz Demo,这是他们提供的代码

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

#3


42  

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

#4


22  

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:

如何使用该函数,假设您子类化UIView并覆盖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:

示例输出:

如何在Core Graphics / Quartz 2D中绘制圆角矩形?

#5


11  

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

如果您想在任何UIView(或子类)上拥有圆角,那么简单的方法就是在视图的层上设置角半径属性。查看iphone中的预览圆形图像

#6


9  

CGPathCreateWithRoundedRect() will do what you want.

CGPathCreateWithRoundedRect()将执行您想要的操作。

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

Available starting in iOS 7.0

从iOS 7.0开始可用

#7


5  

Swift:

迅速:

    let rect: CGRect = ...

    let path = UIBezierPath(roundedRect: rect, cornerRadius: 5.0)
    CGContextAddPath(context, path.CGPath)
    CGContextSetStrokeColorWithColor(context, UIColor.clearColor().CGColor)
    CGContextDrawPath(context, CGPathDrawingMode.FillStroke)

#8


1  

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

#1


123  

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.

在iOS 3.2或更高版本中可用。

#2


56  

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

没有预先打包的方法,你必须合并弧才能做到这一点,apple quartzdemo项目展示了做这个的代码,这是一个引用Quartz Demo,这是他们提供的代码

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

#3


42  

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

#4


22  

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:

如何使用该函数,假设您子类化UIView并覆盖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:

示例输出:

如何在Core Graphics / Quartz 2D中绘制圆角矩形?

#5


11  

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

如果您想在任何UIView(或子类)上拥有圆角,那么简单的方法就是在视图的层上设置角半径属性。查看iphone中的预览圆形图像

#6


9  

CGPathCreateWithRoundedRect() will do what you want.

CGPathCreateWithRoundedRect()将执行您想要的操作。

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

Available starting in iOS 7.0

从iOS 7.0开始可用

#7


5  

Swift:

迅速:

    let rect: CGRect = ...

    let path = UIBezierPath(roundedRect: rect, cornerRadius: 5.0)
    CGContextAddPath(context, path.CGPath)
    CGContextSetStrokeColorWithColor(context, UIColor.clearColor().CGColor)
    CGContextDrawPath(context, CGPathDrawingMode.FillStroke)

#8


1  

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