【问题标题】:How to draw a rounded rectangle in Core Graphics / Quartz 2D?如何在 Core Graphics / Quartz 2D 中绘制圆角矩形?
【发布时间】:2011-02-19 14:19:53
【问题描述】:

我需要画一个圆角矩形的轮廓。我知道我可以制作直线和圆弧,但也许还有圆角矩形的功能?

【问题讨论】:

标签: iphone quartz-graphics


【解决方案1】:

没有预先打包的方法,您必须结合弧才能做到这一点,apples 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); 

【讨论】:

  • 如果有人想知道CGContextAddArcToPoint() 的工作原理,this 是一个很好的解释。
【解决方案2】:

斯威夫特 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()

【讨论】:

    【解决方案3】:

    斯威夫特:

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

    【讨论】:

      【解决方案4】:

      也许……三个?晚了几年,但这些天我使用它没有问题。

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

      【讨论】:

        【解决方案5】:

        CGPathCreateWithRoundedRect() 会做你想做的事。

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

        从 iOS 7.0 开始提供

        【讨论】:

        • 我很确定这不会给你新的 iOS7 圆角。对新的 iOS7 圆角使用 bezierPathWithRoundedRect...
        • @JoeBlow 不知道你的意思,这个功能只在iOS7中添加,给你圆角;还有其他圆角吗?
        【解决方案6】:
         UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:bubbleBounds cornerRadius:15.0];
         CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
         [bezierPath stroke];
        

        【讨论】:

          【解决方案7】:

          这是我编写的一个函数,它使用角半径对输入矩形进行四舍五入。

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

          如何使用该函数,假设您继承 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);
          }
          

          示例输出:

          【讨论】:

          • 继续使用内置函数。我做这个只是为了学习。
          • 这不起作用:CGMutablePathRef path = createRoundedCornerPath(insetRect, outlineCornerRadius);
          • 确保您已经复制了我的回复中包含的 createRoundedCornerPath() 函数的实现。它也必须放在 drawRect: 方法之上,因为它是一个 C 函数。
          • 看看 BezierPath。更容易画出这样的想法
          【解决方案8】:

          您可以使用

          [UIBezierPath bezierPathWithRoundedRect:cornerRadius:]
          

          [UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:]
          

          (第二个让你指定哪些角是圆角)

          适用于 iOS 3.2 或更高版本。

          【讨论】:

          • 即使你的线宽只有一个像素,也不要忘记在描边时正确插入矩形:CGRectInset(rect, lineWidth, lineWidth)
          • 为了完整起见,展示您的处理方式也很有帮助:objc [[UIColor lightGrayColor] setFill]; // set rounded rect's bg color UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect: _yourDrawingFrame cornerRadius: 4]; [roundedRect fillWithBlendMode: kCGBlendModeNormal alpha:1.0f];
          • 实际上在抚摸时我相信矩形应该只插入 lineWidth 的一半,即CGRectInset(rect, lineWidth/2.0, lineWidth/2.0)。这是因为“绘制的线以路径为中心,其两侧与路径段平行”(参见-[UIBezierPath strokeWithBlendMode:alpha:]
          • 如果您更喜欢 CoreGraphics 方法并仅支持 iOS 7.0 及更高版本,也可以使用 CGPathAddRoundedRect
          【解决方案9】:

          如果您想在任何 UIView(或子类)上使用圆角,简单的方法是在视图层上设置cornerRadius 属性。见Preview rounded image in iphone

          【讨论】:

          • 这是迄今为止最简单的。 view.layer.cornerRadius = 10.0f。确保导入 Quartz 框架。
          猜你喜欢
          • 1970-01-01
          • 2012-08-13
          • 2011-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多