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 楼
请注意以下事实:如果您附加了布局约束,则必须在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
设置为基于CGPathRef
的view.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 = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath(roundedRect:detailsSubView.bounds,byRoundingCorners:[.topLeft,.topRight],cornerRadii:CGSize(width: 20,高度:20))。cgPath detailsSubView.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 4extension 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)
}
}
评论
编辑后,需要解决三件事:(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