给UIView添加圆角

613

我的登录视图包含一个子视图,其中包含一个 UIActivityView 和一个标签UILabel说“正在登录中...”。这个子视图的角没有圆角。如何使它们变成圆角?

是否有办法在我的xib文件中完成它?


6
在 IB 中实现这样的效果需要使用带有圆角的预渲染图片。 - Ed Marty
10
@ed-marty并不是必需的,来自@Gujamin的此答案值得一提,因为它展示了如何仅使用Interface Builder将cornerRadius属性应用于表格,而无需使用预先渲染的图像或在代码中设置它。 - djskinner
1
来自@S.P.的内容:http://www.iphonedevsdk.com/forum/tutorial-requests/18807-rounded-corners-uiview.html#post85415 - rptwsthi
21个回答

1269

尝试这个

#import <QuartzCore/QuartzCore.h> // not necessary for 10 years now  :)

...

view.layer.cornerRadius = 5;
view.layer.masksToBounds = true;

注意:如果您试图将圆角应用于 UIViewController 的视图,它不应该应用在视图控制器的构造函数中,而是在-viewDidLoad中,在实际实例化view之后应用。


6
注意,此属性仅存在于iPhone 3.0版本中,之前的版本没有。 - Kendall Helmstetter Gelner
6
我必须说,这是我在SO上见过的最令人满意的答案之一。先在这里检查一下,让我省了一小时与图像编辑器的斗争,并且能够让我的视图更加稳定,不受颜色/大小变化的影响。谢谢! - Justin Searls
20
相关提示:任何对更多可视化元素(如阴影)感兴趣并希望轻松应用于UIView的人都应该查看CALayer类参考。大部分情况下只需设置一两个属性值,就像上面的答案所示。链接:http://developer.apple.com/mac/library/documentation/GraphicsImaging/Reference/CALayer_class/Introduction/Introduction.html - Justin Searls
6
@Ben Collins(或其他遇到此问题的人),请确保您的视图已经设置了“剪裁子视图”。您可以在界面构建器中进行检查。 - zem
2
这个功能很好,但是如果你在任何滚动视图或动画中有很多这样的圆角(我尝试在UITableView中使用它们),你的性能将会大大降低。漂亮流畅的滚动表格很快就会变得卡顿 :( - Slee
显示剩余11条评论

276
您也可以使用界面生成器的用户定义的运行时属性功能来设置键路径layer.cornerRadius的值。但请确保包括QuartzCore库。 这个技巧同样适用于设置layer.borderWidth,但对于layer.borderColor不起作用,因为它需要CGColor而不是UIColor。 您将无法在故事板中看到效果,因为这些参数在运行时评估。 使用界面生成器设置圆角半径

11
请记得在视图的Interface Builder中,勾选剪裁子视图(Clip Subviews)选项。 - Peter
2
添加一个关键路径:layer.masksToBounds,类型:布尔值:已选中。 - Amitabh
在文档大纲中的FxView上设置2个用户定义的运行时属性(layer.cornerRadius和layer.masksToBounds),而不是在其视图上设置。这个答案真是救命稻草!在我使用Xcode 12.3时有效,无需#include <QuartzCore/QuartzCore.h>语句。 - Ugo
在Xcode 12.4中,剪裁子视图的设置可以在“属性检查器”中找到:它是“绘图”部分中的一个复选框,称为“剪裁边界”。 - Neph

77

Swift

简短回答:

myView.layer.cornerRadius = 8
myView.layer.masksToBounds = true  // optional

补充回答

如果您已经看到足够的内容来解决问题,那么您可能已经找到答案了。我添加这个答案是为了更好地解释为什么事情会做什么。

如果您从普通的UIView开始,它具有方形角落。

let blueView = UIView()
blueView.frame = CGRect(x: 100, y: 100, width: 100, height: 50)
blueView.backgroundColor = UIColor.blueColor()
view.addSubview(blueView)

在这里输入图像描述

通过更改视图的layercornerRadius属性,可以使其具有圆角。

blueView.layer.cornerRadius = 8

在这里输入图片描述

半径值越大,圆角就越圆润。

blueView.layer.cornerRadius = 25

输入图像描述

数值越小,圆角越少。

blueView.layer.cornerRadius = 3

输入图像描述

这可能已经足以解决您的问题了。然而,有时视图可以有一个子视图或子图层超出视图的边界。例如,如果我添加一个这样的子视图

let mySubView = UIView()
mySubView.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
mySubView.backgroundColor = UIColor.redColor()
blueView.addSubview(mySubView)

或者如果我像这样添加一个子

let mySubLayer = CALayer()
mySubLayer.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
mySubLayer.backgroundColor = UIColor.redColor().CGColor
blueView.layer.addSublayer(mySubLayer)

那么我最终会得到

在此输入图片描述

现在,如果我不想让内容超出边界,可以这样做

blueView.clipsToBounds = true

或者这个

blueView.layer.masksToBounds = true

这会产生以下结果:

在此输入图片描述

clipsToBoundsmasksToBounds等效的。只是前者用于UIView,而后者用于CALayer

另请参阅


4
我想补充一下,将圆角半径设为短边的一半(在这种情况下为 blueView.frame.size.height/2)会得到一个完美的圆角。 - Johann Burgess

66

现在你可以在UIView中使用一个快捷分类(下面是代码)并使用@IBInspectable在故事板中显示结果(如果您正在使用该类别,请仅使用cornerRadius而不是layer.cornerRadius作为关键路径)。

extension UIView {
    @IBInspectable var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }
}

在此输入图片描述


如果您正在使用自定义子类,请确保使用 @IBDesignable 进行标记,以在 IB 中获得实时预览!(更多信息请参见 http://nshipster.com/ibinspectable-ibdesignable/) - clozach
这在当前的XCode中似乎不起作用。视图在设备上是圆角的,但在IB中不是。 - bias

44
一个不同于Ed Marty所做的方法:
#import <QuartzCore/QuartzCore.h>

[v.layer setCornerRadius:25.0f];
[v.layer setMasksToBounds:YES];

你需要使用setMasksToBounds方法来加载所有从IB中获取的对象... 我遇到一个问题,我的视图被圆角处理,但是没有从IB中获取到的对象 :/

这个方法解决了我的问题 =D 希望它也能帮到你!


49
除了不使用点语法之外,它有什么不同? - user102008
3
[v.layer setMasksToBounds:YES]; 这行代码像魔术一样,解决了我的大问题。 - Cullen SUN
3
我在开始iOS开发时写了这篇文章,当时不知道点语法和方括号语法没有区别,所以我把它们写成了“不同”。我的代码还包括了Ed Marty原始回答中缺少的import <> (后来进行了编辑),因此我的回答能够帮助人们解决问题(即没有导入它的情况)。 - Kristian Flatheim Jensen

28

这篇博客文章所述,这是一个用于给UIView的角落设置圆角的方法:

+(void)roundView:(UIView *)view onCorner:(UIRectCorner)rectCorner radius:(float)radius
{
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds
                                                   byRoundingCorners:rectCorner
                                                         cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = view.bounds;
    maskLayer.path = maskPath.CGPath;
    [view.layer setMask:maskLayer];
    [maskLayer release];
}

最酷的部分是你可以选择哪些角要圆角化。


6
与其只提供外部网站链接,我们更喜欢答案在此处能够自成一体,因此我将相关的代码从被链接的博客文章中带到了您的回答中。人们可以访问博客文章以获得更多细节,但这确保了内容即使该帖子消失也会保存下来。此外,您将此回答发布到了几个不同的问题上,但这些问题并没有真正询问相同的事情。它们已被删除,其中一个问题被关闭为重复问题。我们喜欢有针对性地回答每个问题。 - Brad Larson
5
Prescient. 这篇博客文章现在已经无法访问。 - Anthony C
这种方法很干净,但它会隐藏视图上的任何阴影效果。 - geekay

22
您可以使用以下自定义的UIView类,该类还可以更改边框颜色和宽度。由于这是IBDesignalbe,您也可以在界面构建器中更改属性。

输入图像描述

import UIKit

@IBDesignable public class RoundedView: UIView {

    @IBInspectable var borderColor: UIColor = UIColor.white {
        didSet {
            layer.borderColor = borderColor.cgColor
        }
    }

    @IBInspectable var borderWidth: CGFloat = 2.0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }

    @IBInspectable var cornerRadius: CGFloat = 0.0 {
        didSet {
            layer.cornerRadius = cornerRadius
        }
    }

}

我对Swift还比较陌生,这个有Swift版本吗? - ralphgabb

20

你需要先导入头文件 <QuartzCore/QuartzCore.h>

 #import QuartzCore/QuartzCore.h>

[yourView.layer setCornerRadius:8.0f];
yourView.layer.borderColor = [UIColor redColor].CGColor;
yourView.layer.borderWidth = 2.0f;
[yourView.layer setMasksToBounds:YES];

不要忘记使用 -setMasksToBounds ,否则可能无法显示效果。


2
不需要导入 "QuartzCore/QuartzCore.h"。 - Sudhir Kumar
是的,你确实需要导入。 - Lord Zsolt
3
也许他们在iOS7中已经改变了这一点,但是现在你不需要再导入QuartzCore了。 - Marc

8
view.layer.cornerRadius = 25
view.layer.masksToBounds = true

6
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 50, 200, 200)];

view.layer.backgroundColor = [UIColor whiteColor].CGColor;
view.layer.cornerRadius = 20.0;
view.layer.frame = CGRectInset(v.layer.frame, 20, 20);

view.layer.shadowOffset = CGSizeMake(1, 0);
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowRadius = 5;
view.layer.shadowOpacity = .25;

[self.view addSubview:view];
[view release];

应用 setMasksToBounds 是重要的。设置背景颜色和投影不是必须的。 - djskinner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,