【问题标题】:IOS - Drawing rounded corner squareIOS - 绘制圆角正方形
【发布时间】:2014-05-14 09:43:51
【问题描述】:

我正在尝试创建一个 200 像素的圆角正方形,以用作 IOS 吐司样式指示。

到目前为止,我有以下 -

- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.1].CGColor);
    CGContextMoveToPoint(context, 10, 0);
    CGContextAddLineToPoint(context, 95, 0);
    CGContextAddArcToPoint(context, 100, 0, 100, 5, 10);
    CGContextAddLineToPoint(context, 100, 95);
    CGContextAddArcToPoint(context, 100, 100, 95, 100, 10);
    CGContextAddLineToPoint(context, 5, 100);
    CGContextAddArcToPoint(context, 0, 100, 0, 95, 10);
    CGContextAddLineToPoint(context, 0, 5);
    CGContextAddArcToPoint(context, 0, 0, 5, 0, 10);
    CGContextFillPath(context);
}

我是按照教程完成的——它绘制了一个完美的 100 像素圆角正方形——但我需要一个 150 像素的正方形!我已经改变了每一个可以想象的设置 - 有一些奇怪的结果 - 但无法弄清楚宽度高度是如何定义的!?谁能给点建议?

【问题讨论】:

  • 150 还是 200?我不清楚
  • 如果这就是您要查找的全部内容,请查看 Simon 的答案。该框架为您提供所需的一切。对于更复杂的表格,核心图形真的很有帮助。当您使用核心图形绘制自己的图形时,我建议使用变量(或常量开始),例如 with、height 和 conerRadius。首先,它更容易编程。但其次,它更灵活。然后,您只需将宽度和高度从 100 更改为 150 即可。

标签: ios objective-c cgcontext


【解决方案1】:

Swift 更新:

下面的答案是正确的,它是为简单的用例编写的。从那以后情况发生了很大变化,所以这里有一个 swift 的更新答案。

您可以创建一个 UIView 扩展,以添加方法来圆所有角或圆特定角。将@IBInspectable添加到第一个属性意味着它可以在界面构建器中使用而无需代码

第二个函数比较复杂,不能直接作为@IBInspectable使用。需要在父级的 viewDidLayoutSubviews 内调用它,以确保掩码不会随着 AutoLayout 增长/缩小内容而切断内容。

extension UIView {

    @IBInspectable public var cornerRadius: CGFloat {
        set {
            layer.cornerRadius = newValue
        }
        get {
            return layer.cornerRadius
        }
    }

    public func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    }
}

添加到您的项目后,您只需执行以下操作:

myView.cornerRadius = 4

or

myView.roundCorners(corners: [.topLeft, .topRight], radius: 4)

非常古老的 Objective-c 答案:

如果你导入 QuartzCore 框架:

#import <QuartzCore/QuartzCore.h>

并将其添加到您的项目中,您可以使用以下内容:

UIView *temp = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
temp.layer.cornerRadius = 5;

【讨论】:

  • 这种方法有一个问题.. 它需要离屏渲染,如果你在 tableview 单元格元素上这样做(例如)它会降低滚动性能
  • 这将作为 toast 样式更新通知添加到 uitableviewcontroller - 在这种情况下,我最好在下面实施 Templar 的解决方案吗?
  • @Andrea 同意,但用户说他们正在尝试创建 iOS 吐司样式指示。它将用作屏幕上的弹出消息。我认为给用户一个更简单的理解方法会更容易
  • @downVoter 需要解释一下吗? 3 人赞成,其他人说这是解决这个问题的好方法。当人们在这种情况下投反对票时,我很生气。显然,您对我的某些代码有疑问,我很想知道,以便我可以像用户一样从中学习。请分享
  • @Dancer Nah,在这种情况下,使用cornerRadius 会容易得多。一般只有在需要特殊形状、渐变等的时候才使用drawRect。
【解决方案2】:

如果您必须在drawRect 中绘制并且将来会绘制其他东西,那么只需使用 bezierpath,否则请参阅 Simon 对视图上简单圆角的回答

- (void)drawRect:(CGRect)rect {
       [super drawRect:rect];
       [[UIColor blueColor] setFill];
       UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect /*CGRectMake(0, 0, 150, 150)*/ cornerRadius:10.0];
       [path fill];
}

【讨论】:

    【解决方案3】:
    1. 将数字转换为变量/常数。

    2. 更改变量/常量值。

    3. 利润!

    这是您的代码,经过修改以显示我的意思(未经测试):

    - (void)drawRect:(CGRect)rect {
        static CGFloat length = 100;
        static CGFloat rounding = 5;
    
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.1].CGColor);
        CGContextMoveToPoint(context, rounding * 2, 0);
        CGContextAddLineToPoint(context, length - rounding, 0);
        CGContextAddArcToPoint(context, length, 0, length, rounding, rounding * 2);
        CGContextAddLineToPoint(context, length, length - rounding);
        CGContextAddArcToPoint(context, length, length, length - rounding, length, rounding * 2);
        CGContextAddLineToPoint(context, rounding, length);
        CGContextAddArcToPoint(context, 0, length, 0, length - rounding, rounding * 2);
        CGContextAddLineToPoint(context, 0, rounding);
        CGContextAddArcToPoint(context, 0, 0, rounding, 0, rounding * 2);
        CGContextFillPath(context);
    }
    

    我也想知道你代码中的 10s。据我所知,它们应该是 5s。无论如何,更简单的解决方案是使用UIBezierPath,正如其他人所展示的那样(图层解决方案确实有效,但如果您想在圆角矩形下方和上方绘制一些东西,它显然不起作用)。

    【讨论】:

      【解决方案4】:

      为什么不使用贝塞尔路径?

      CGFloat radius =  4;
      CGRect rect = CGRectMake(0,0,200,200);
      UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
      [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.1] setFill];
      [path fill];
      

      【讨论】: