有没有办法只为cornerRadius的左上角和右上角设置UIView

我尝试了以下操作,但最终看不到该视图。

UIView *view = [[UIView alloc] initWithFrame:frame];

CALayer *layer = [CALayer layer];
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight) cornerRadii:CGSizeMake(3.0, 3.0)];
layer.shadowPath = shadowPath.CGPath;
view.layer.mask = layer;


评论

编辑后,需要解决三件事:(1)圆角路径应基于view.bounds,而不是框架;(2)图层应为CAShapeLayer,而不是CALayer; (3)设置图层的路径,而不是shadowPath。

此问题和答案的可能重复。

使用Bezier曲线算法,在CGPath上创建曲线。我很确定它是CoreGraphics的一部分。如果没有,en.wikipedia.org / wiki /Bézier_curve具有一些很棒的定义和动画。

iosdevcenters.blogspot.com/2018/02/…

在这里查看我的答案:stackoverflow.com/a/50396485/6246128

#1 楼

请注意以下事实:如果您附加了布局约束,则必须在UIView子类中按如下所示刷新它:

override func layoutSubviews() {
    super.layoutSubviews()
    roundCorners(corners: [.topLeft, .topRight], radius: 3.0)
}


如果不这样做它不会显示出来。


圆角处,使用扩展名:

extension UIView {
   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
    }
}




其他视图控制器案例:无论您是否愿意或不希望对视图进行子类化,您仍然可以对视图进行四舍五入。通过覆盖viewWillLayoutSubviews()函数从其视图控制器执行此操作,如下所示:

class MyVC: UIViewController {
    /// The view to round the top-left and top-right hand corners
    let theView: UIView = {
        let v = UIView(frame: CGRect(x: 10, y: 10, width: 200, height: 200))
        v.backgroundColor = .red
        return v
    }()

    override func loadView() {
        super.loadView()
        view.addSubview(theView)
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        // Call the roundCorners() func right there.
        theView.roundCorners(corners: [.topLeft, .topRight], radius: 30)
    }
}


评论


这绝对不是一个答案,作者问的是如何使特定的角变圆,而不是如何使角半径与布局更改同步。

– kelin
18 Mar 11 '18在10:37



这是没有道理的答案。

– Tiago Couto
18年8月13日在1:30

答案最近已经确定.. @kelin

–迈克尔
18-10-13在14:38

这肯定圆了。

–aznelite89
19年1月16日在9:47

视图出现后,您必须执行此操作

–乔纳森。
1月6日23:45



#2 楼

我不确定为什么您的解决方案不起作用,但是以下代码对我有用。创建贝塞尔曲线蒙版并将其应用于您的视图。在下面的代码中,我将_backgroundView的底角圆角化为3个像素。 self是自定义的UITableViewCell

UIBezierPath *maskPath = [UIBezierPath
    bezierPathWithRoundedRect:self.backgroundImageView.bounds
    byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight)
    cornerRadii:CGSizeMake(20, 20)
];

CAShapeLayer *maskLayer = [CAShapeLayer layer];

maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;

self.backgroundImageView.layer.mask = maskLayer;


带有一些改进的Swift版本:

let path = UIBezierPath(roundedRect:viewToRound.bounds, byRoundingCorners:[.TopRight, .BottomLeft], cornerRadii: CGSizeMake(20, 20))
let maskLayer = CAShapeLayer()

maskLayer.path = path.CGPath
viewToRound.layer.mask = maskLayer


Swift 3.0版本:

let path = UIBezierPath(roundedRect:viewToRound.bounds,
                        byRoundingCorners:[.topRight, .bottomLeft],
                        cornerRadii: CGSize(width: 20, height:  20))

let maskLayer = CAShapeLayer()

maskLayer.path = path.cgPath
viewToRound.layer.mask = maskLayer


在此处快速扩展

评论


在文本字段中尝试。左成功,右失败

–廖雨娜
15年8月20日在9:36

@RainerLiao我有同样的问题,我在viewDidLoad方法上完成了所有这些工作,将其移至viewDidAppear并正常工作。

– Lucho
2015年9月9日19:31

如何将其设置为适用于任何设备。这仅适用于情节提要中的模拟器大小。例如:如果模拟器的大小为6s,则可以在6s内正常工作,但其他情况下则不能。我该如何克服这个问题。

–Chanaka Anuradh火山口
16-09-21在12:19

Swift 3版本中的小语法错误:path.CGPath应该是path.cgPath

–Rob
16-10-18在12:05

@RainerLiao如果您不希望它随着视图的显示而滑动,请将其更改为viewWillAppear。这也有效。

–马修·肯尼彭(Matthew Knippen)
16 Dec 13'17:39



#3 楼

这是@JohnnyRockex的Swift版本答案

extension UIView {

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

}



view.roundCorners([.topLeft, .bottomRight], radius: 10)


注意

如果使用自动版式时,您需要将UIView子类化,并在视图的roundCorners中调用layoutSubviews以获得最佳效果。

class View: UIView {
    override func layoutSubviews() {
        super.layoutSubviews()

        self.roundCorners([.topLeft, .bottomLeft], radius: 10)
    }
}


评论


很好的扩展。但是:.TopRight和.BottomRight似乎对我不起作用。

– Onichan
15年3月25日在10:06

在Swift 2上:view.roundCorners([。TopLeft,.BottomLeft],半径:10)

– fahrulazmi
2015年9月17日在7:53

它无法在“右侧”上运行,因为您的视图范围尚未使用自动布局进行很好的定义...我目前正面临着同样的问题。

–dosdos
15年10月28日在9:50

@dosdos视图的子类,并在layoutSubviews中围绕自身。

– Arbitur
15年10月28日在10:02

如果使用自动布局,并且没有要舍入的视图引用,则可以调用.layoutIfNeeded(),然后调用此方法。

– zgjie
16年5月18日在8:41

#4 楼

最后…iOS11中有CACornerMask!
CACornerMask可以很容易地做到:

let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 10
view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // Top right corner, Top left corner respectively


评论


这绝对是最好的。在舍入动态调整tableview单元大小的边缘时,其他解决方案总是存在问题。

–cornr
17年11月13日在12:05

旧版本将如何处理? self.layer.maskedCorners = [.layerMaxXMaxYCorner,.layerMinXMaxYCorner,.layerMaxXMinYCorner]

– SHEBIN
18年1月29日在19:11



@SHEBIN,尝试使用此页面上其他答案的解决方案

–谢尔盖·贝卢斯(Sergey Belous)
18年1月30日在8:11

其他答案在旋转设备时不起作用,此代码可旋转,并且允许您将某些角转成圆角,这应该是公认的答案。

–Cloud9999Strife
18-10-3在12:37

不需要设置“ view.clipsToBounds = true”。否则,它可能会对Shadow产生一些副作用(如果还应用了阴影)

–穆罕默德·纳亚布(Muhammad Nayab)
19年12月6日上午11:07

#5 楼

此处的Swift代码示例:https://stackoverflow.com/a/35621736/308315


不是直接的。您将必须:


创建CAShapeLayer

将其path设置为基于CGPathRefview.bounds,但只有两个圆角(可能使用+[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:]
将您的view.layer.mask设置为CAShapeLayer



评论


请注意,如果您仅凭几个观点这样做会损害性能...

– jjxtra
2012年6月18日在21:15

@jjxtra那么,在没有太多性能损失的情况下实现它的最佳方法是什么?我想在UITableViewCell中显示它。

– xi.lin
16-4-18的2:06

我记得设置layer.shouldRasterize == YES时@ xi.lin可以将速度提高5倍左右。但是文档说,只有在使用非透明单元格时,它才有效。试一试。

– codrut
17-10-9在8:22

#6 楼

这是一个像这样实现的简短方法:

- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *openInMaps = [UIButton new];
    [openInMaps setFrame:CGRectMake(15, 135, 114, 70)];
    openInMaps = (UIButton *)[self roundCornersOnView:openInMaps onTopLeft:NO topRight:NO bottomLeft:YES bottomRight:NO radius:5.0];
}

- (UIView *)roundCornersOnView:(UIView *)view onTopLeft:(BOOL)tl topRight:(BOOL)tr bottomLeft:(BOOL)bl bottomRight:(BOOL)br radius:(float)radius {

    if (tl || tr || bl || br) {
        UIRectCorner corner = 0;
        if (tl) {corner = corner | UIRectCornerTopLeft;}
        if (tr) {corner = corner | UIRectCornerTopRight;}
        if (bl) {corner = corner | UIRectCornerBottomLeft;}
        if (br) {corner = corner | UIRectCornerBottomRight;}

        UIView *roundedView = view;
        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:roundedView.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(radius, radius)];
        CAShapeLayer *maskLayer = [CAShapeLayer layer];
        maskLayer.frame = roundedView.bounds;
        maskLayer.path = maskPath.CGPath;
        roundedView.layer.mask = maskLayer;
        return roundedView;
    }
    return view;
}


评论


设置颜色呢? maskLayer.borderWidth = 10; maskLayer.borderColor = [UIColor redColor] .CGColor;先生,这对我不起作用。

–基兰
18年2月16日在15:52

@kiran遮罩没有颜色,如果要有边框,可以添加第二个CAShapeLayer

–约翰尼·洛克克斯(Johnny Rockex)
18-2-20在16:21



#7 楼

在Swift 4.1和Xcode 9.4.1中
在iOS 11中,这一行就足够了:
detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]//Set your view here

请参见完整的代码: />
//In viewDidLoad
if #available(iOS 11.0, *) {
        detailsSubView.clipsToBounds = false
        detailsSubView.layer.cornerRadius = 10
        detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
} else {
      //For lower versions
}

完整代码是。
let rectShape = CAShapeLayer()
    rectShape.bounds = detailsSubView.frame
    rectShape.position = detailsSubView.center
    rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
    detailsSubView.layer.mask = rectShape

如果在情节提要中使用自动调整大小,请在viewDidLayoutSubviews()中编写此代码。
if #available(iOS 11.0, *) {
    detailsSubView.clipsToBounds = false
    detailsSubView.layer.cornerRadius = 10
    detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
} else {
    let rectShape = CAShapeLayer()
    rectShape.bounds = detailsSubView.frame
    rectShape.position = detailsSubView.center
    rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
    detailsSubView.layer.mask = rectShape
}


评论


iOS 9的任何解决方案?

– J.D
19年2月14日在9:25

@jay let rectShape = CAShapeLayer()rectShape.bounds = detailsS​​ubView.frame rectShape.position = detailsS​​ubView.center rectShape.path = UIBezierPath(roundedRect:detailsS​​ubView.bounds,byRoundingCorners:[.topLeft,.topRight],cornerRadii:CGSize(width: 20,高度:20))。cgPath detailsS​​ubView.layer.mask = rectShape此代码适用于iOS 9

– iOS
19年2月14日在9:29

@jay检查是否没有通知我

– iOS
19年2月14日在9:29

不适用于ios9。角落部分没有边框。

– J.D
19年2月14日在9:41

@jay我没有iOS 9操作系统的电话,但是我签入了iOS 9模拟器。它正在运作...如何以及在何处进行检查。你能建议我签入iOS 9吗

– iOS
19年2月14日在9:54

#8 楼

iOS 11,Swift 4
您可以尝试以下代码:

if #available(iOS 11.0, *) {
   element.clipsToBounds = true
   element.layer.cornerRadius = CORNER_RADIUS
   element.layer.maskedCorners = [.layerMaxXMaxYCorner]
} else {
   // Fallback on earlier versions
}


您可以在表视图单元格中使用它。

评论


这是当今编码的正确答案。再见,遮罩层。

–梁爱玲
18-10-28在9:49

这一定是最好的答案!

– fujianjin6471
19年3月3日在10:55

#9 楼

这是最简单的答案:

yourView.layer.cornerRadius = 8
yourView.layer.masksToBounds = true
yourView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]


评论


标记这是适用于iOS 11或更高版本的解决方案

–安库尔·拉希尔(Ankur Lahiry)
2月20日下午5:19

#10 楼

1行中的Swift 4 Swift 5简单方法

用法:

//MARK:- Corner Radius of only two side of UIViews
self.roundCorners(view: yourview, corners: [.bottomLeft, .topRight], radius: 12.0)


功能:

//MARK:- Corner Radius of only two side of UIViews
func roundCorners(view :UIView, corners: UIRectCorner, radius: CGFloat){
        let path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        view.layer.mask = mask
}


在Objective-C中

用法:

[self.verticalSeparatorView roundCorners:UIRectCornerTopLeft radius:10.0];

在类别(仅一个角)中使用的函数:

-(void)roundCorners: (UIRectCorner) corners radius:(CGFloat)radius {
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
        CAShapeLayer *mask = [[CAShapeLayer alloc] init];
        mask.path = path.CGPath;
        self.layer.mask = mask;
    }


评论


仅记住,在完成viewDidLayoutSubviews之前,不会计算视图的角,因此您应该在其中调用roundCorners函数

–杰森·塔维拉(Jirson Tavera)
19年5月15日在19:54

您能告诉我如何在此视图中添加阴影吗?

– Vadlapalli Masthan
19年6月19日在13:57

@ShakeelAhmed如果要向视图添加阴影,则此方法将无效。

– mojtaba al Moussawi
19年7月2日在7:39

首先添加拐角半径,然后添加阴影

– Shakeel Ahmed
19年7月2日在7:40

@JirsonTavera感谢小费,这让我发疯,几乎花了我一个小时才能在这里找到您的评论!

–阿拉什·阿普夏普(Arash Afsharpour)
6月23日,2:02

#11 楼

尝试以下代码,

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:( UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(5.0, 5.0)];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.view.bounds;
maskLayer.path  = maskPath.CGPath;

view.layer.mask = maskLayer;


#12 楼

艾玛:.TopRight.BottomRight不适用于您,可能是因为在计算最终view.roundCorners之前已完成对view bounds的调用。请注意,Bezier Path从调用时的视图范围派生。例如,如果自动布局会缩小视图范围,则右侧的圆角可能不在视图范围内。
请尝试在viewDidLayoutSubviews中调用该视图,该视图的边界是最终的。

评论


谢谢。对我来说,解决问题的方法是将对“ Arbitur”给出的实现的调用从viewDidLoad和viewWillAppear移到viewDidAppear。我可以这样做,因为我的控件最初设置为隐藏。

–马蒂
15年8月26日在7:30

你是对的。它将产生自动布局问题,您做得很好。

– Ashish Kakkad
16年1月12日,11:57

#13 楼

快速解决UIView和UITextFiels特定角的解决方案是使用

.br.layer.cornerRadius





layer.maskedCorners


实际的UIView或UITextFields。

示例:

fileprivate func inputTextFieldStyle() {
        inputTextField.layer.masksToBounds = true
        inputTextField.layer.borderWidth = 1
        inputTextField.layer.cornerRadius = 25
        inputTextField.layer.maskedCorners = [.layerMaxXMaxYCorner,.layerMaxXMinYCorner]
        inputTextField.layer.borderColor = UIColor.white.cgColor
    }


并使用


.layerMaxXMaxYCorner





.layerMaxXMinYCorner
/>

,我可以指定要舍入的UITextField的右上角和右下角。

您可以在此处查看结果:



评论


完美的边框和特定角落组合🎉🎉🎉

–nomnom
1月22日下午16:41

完美的解决方案

– Manish Singh
10月20日17:54

#14 楼

Swift 4

extension UIView {

    func roundTop(radius:CGFloat = 5){
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        if #available(iOS 11.0, *) {
            self.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
        } else {
            // Fallback on earlier versions
        }
    }

    func roundBottom(radius:CGFloat = 5){
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        if #available(iOS 11.0, *) {
            self.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
        } else {
            // Fallback on earlier versions
        }
    }
}


评论


在我的情况下,您节省了我的一天,我不得不对特定单元格进行四舍五入

– Shakti
19年4月5日在14:05

根据我的要求完美。我使用了所有答案,没有任何帮助,但是您的答案帮助了我,解决了我的问题。

– Nikita Patil
19-10-24在7:13

#15 楼

简单扩展

extension UIView {
    func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        if #available(iOS 11, *) {
            self.clipsToBounds = true
            self.layer.cornerRadius = radius
            var masked = CACornerMask()
            if corners.contains(.topLeft) { masked.insert(.layerMinXMinYCorner) }
            if corners.contains(.topRight) { masked.insert(.layerMaxXMinYCorner) }
            if corners.contains(.bottomLeft) { masked.insert(.layerMinXMaxYCorner) }
            if corners.contains(.bottomRight) { masked.insert(.layerMaxXMaxYCorner) }
            self.layer.maskedCorners = masked
        }
        else {
            let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            layer.mask = mask
        }
    }
}


用法:

view.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 12)


#16 楼

以编程方式执行此操作的方法是在带有圆角的UIView的顶部上方创建一个UIView。或者您可以将顶部隐藏在某些东西下面。

评论


它是一个非常丑陋的解决方案:P

– Arbitur
2014年12月12日在21:03

#17 楼

    // Create the path (with only the top-left corner rounded)
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds 
                           byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) 
                           cornerRadii:CGSizeMake(7.0, 7.0)];

// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = cell.stripBlackImnageView.bounds;
maskLayer.path = maskPath.CGPath; 
// Set the newly created shapelayer as the mask for the image view's layer
view.layer.mask = maskLayer;


#18 楼

最简单的方法是制作具有圆角层的蒙版。

CALayer *maskLayer = [CALayer layer];
maskLayer.frame = CGRectMake(0,0,maskWidth ,maskHeight);
maskLayer.contents = (__bridge id)[[UIImage imageNamed:@"maskImageWithRoundedCorners.png"] CGImage];

aUIView.layer.mask = maskLayer;


不要忘记:

#import <QuartzCore/QuartzCore.h>


#19 楼

已经给出的所有答案都是非常好的和有效的(特别是Yunus使用mask属性的想法)。

但是我需要更复杂的东西,因为我的图层经常会改变大小,这意味着我需要

我每次都使用该遮罩逻辑,这有点烦人。

我使用了快速的extensions并计算了属性,以构建一个真正的cornerRadii属性,该属性负责在布局图层时自动更新遮罩。 br />
这是使用Peter Steinberg出色的Aspects库进行转换实现的。

完整的代码在这里:

extension CALayer {
  // This will hold the keys for the runtime property associations
  private struct AssociationKey {
    static var CornerRect:Int8 = 1    // for the UIRectCorner argument
    static var CornerRadius:Int8 = 2  // for the radius argument
  }

  // new computed property on CALayer
  // You send the corners you want to round (ex. [.TopLeft, .BottomLeft])
  // and the radius at which you want the corners to be round
  var cornerRadii:(corners: UIRectCorner, radius:CGFloat) {
    get {
      let number = objc_getAssociatedObject(self, &AssociationKey.CornerRect)  as? NSNumber ?? 0
      let radius = objc_getAssociatedObject(self, &AssociationKey.CornerRadius)  as? NSNumber ?? 0
      return (corners: UIRectCorner(rawValue: number.unsignedLongValue), radius: CGFloat(radius.floatValue))
    }
    set (v) {
      let radius = v.radius
      let closure:((Void)->Void) = {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: v.corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.CGPath
        self.mask = mask
      }
      let block: @convention(block) Void -> Void = closure
      let objectBlock = unsafeBitCast(block, AnyObject.self)
      objc_setAssociatedObject(self, &AssociationKey.CornerRect, NSNumber(unsignedLong: v.corners.rawValue), .OBJC_ASSOCIATION_RETAIN)
      objc_setAssociatedObject(self, &AssociationKey.CornerRadius, NSNumber(float: Float(v.radius)), .OBJC_ASSOCIATION_RETAIN)
      do { try aspect_hookSelector("layoutSublayers", withOptions: .PositionAfter, usingBlock: objectBlock) }
      catch _ { }
    }
  }
}


I写了一个简单的博客文章来解释这一点。

#20 楼

如果您正在寻找仅用于界面构建器的解决方案,那么有一个适用于iOS 11及更高版本的解决方案。在这里查看我的答案:https://stackoverflow.com/a/58626264

#21 楼

这是使用C#在Xamarin中为按钮的每个角设置角半径的方法:

var maskPath = UIBezierPath.FromRoundedRect(MyButton.Bounds, UIRectCorner.BottomLeft | UIRectCorner.BottomRight,
    new CGSize(10.0, 10.0));
var maskLayer = new CAShapeLayer
{
    Frame = MyButton.Bounds,
    Path = maskPath.CGPath
};
MyButton.Layer.Mask = maskLayer;


#22 楼

重用Yunus Nedim Mehel解决方案的可爱扩展

Swift 2.3

extension UIView {
func roundCornersWithLayerMask(cornerRadii: CGFloat, corners: UIRectCorner) {
    let path = UIBezierPath(roundedRect: bounds,
                            byRoundingCorners: corners,
                            cornerRadii: CGSize(width: cornerRadii, height: cornerRadii))
    let maskLayer = CAShapeLayer()
    maskLayer.path = path.CGPath
    layer.mask = maskLayer
} }


用法

let view = UIView()
view.roundCornersWithLayerMask(10,[.TopLeft,.TopRight])


评论


不错的干净解决方案

–侵略者
18年4月19日在15:54

#23 楼

更改代码后@apinho在swift 4.3中工作正常

extension UIView {
func roundCornersWithLayerMask(cornerRadii: CGFloat, corners: UIRectCorner) {
    let path = UIBezierPath(roundedRect: bounds,
                            byRoundingCorners: corners,
                            cornerRadii: CGSize(width: cornerRadii, height: cornerRadii))
    let maskLayer = CAShapeLayer()
    maskLayer.path = path.cgPath
    layer.mask = maskLayer
  }
}


要使用此功能查看

YourViewName. roundCornersWithLayerMask(cornerRadii: 20,corners: [.topLeft,.topRight])


#24 楼

斯蒂芬答案的另一个版本。

import UIKit

    class RoundCornerView: UIView {
    var corners : UIRectCorner = [.topLeft,.topRight,.bottomLeft,.bottomRight]
        var roundCornerRadius : CGFloat = 0.0
        override func layoutSubviews() {
            super.layoutSubviews()
            if corners.rawValue > 0 && roundCornerRadius > 0.0 {
                self.roundCorners(corners: corners, radius: roundCornerRadius)
            }
        }
        private 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
        }

    }


#25 楼

在Swift 4.2中,通过@IBDesignable进行创建,如下所示:

@IBDesignable

class DesignableViewCustomCorner: UIView {

    @IBInspectable var cornerRadious: CGFloat = 0 {
        didSet {
            let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadious, height: cornerRadious))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            self.layer.mask = mask
        }
    }

}


#26 楼

对于SwiftUI
,我找到了这些解决方案,您可以从这里查看https://stackoverflow.com/a/56763282/3716103
我强烈建议第一个解决方案
选项1:使用Path + GeometryReader
(有关GeometryReader的更多信息:https://swiftui-lab.com/geometryreader-to-the-rescue/)
struct ContentView : View {
    var body: some View {

        Text("Hello World!")
            .foregroundColor(.white)
            .font(.largeTitle)
            .padding(20)
            .background(RoundedCorners(color: .blue, tl: 0, tr: 30, bl: 30, br: 0))
    }
}


RoundedCorners
struct RoundedCorners: View {

    var color: Color = .white

    var tl: CGFloat = 0.0
    var tr: CGFloat = 0.0
    var bl: CGFloat = 0.0
    var br: CGFloat = 0.0

    var body: some View {
        GeometryReader { geometry in
            Path { path in

                let w = geometry.size.width
                let h = geometry.size.height

                // Make sure we do not exceed the size of the rectangle
                let tr = min(min(self.tr, h/2), w/2)
                let tl = min(min(self.tl, h/2), w/2)
                let bl = min(min(self.bl, h/2), w/2)
                let br = min(min(self.br, h/2), w/2)

                path.move(to: CGPoint(x: w / 2.0, y: 0))
                path.addLine(to: CGPoint(x: w - tr, y: 0))
                path.addArc(center: CGPoint(x: w - tr, y: tr), radius: tr, startAngle: Angle(degrees: -90), endAngle: Angle(degrees: 0), clockwise: false)
                path.addLine(to: CGPoint(x: w, y: h - be))
                path.addArc(center: CGPoint(x: w - br, y: h - br), radius: br, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 90), clockwise: false)
                path.addLine(to: CGPoint(x: bl, y: h))
                path.addArc(center: CGPoint(x: bl, y: h - bl), radius: bl, startAngle: Angle(degrees: 90), endAngle: Angle(degrees: 180), clockwise: false)
                path.addLine(to: CGPoint(x: 0, y: tl))
                path.addArc(center: CGPoint(x: tl, y: tl), radius: tl, startAngle: Angle(degrees: 180), endAngle: Angle(degrees: 270), clockwise: false)
            }
            .fill(self.color)
        }
    }
}

RoundedCorners_Previews
struct RoundedCorners_Previews: PreviewProvider {
    static var previews: some View {
        RoundedCorners(color: .pink, tl: 40, tr: 40, bl: 40, br: 40)
    }
}