我想创建一个带有圆顶边的UIView,就像这张图片一样,我该怎么办呢?
通缉结果
不想要的结果
答案 0 :(得分:2)
This answer真的帮助了我 我通过这段代码实现了这个效果:
Swift 3.1
extension UIView {
func addBottomRoundedEdge(desiredCurve: CGFloat?) {
let offset: CGFloat = self.frame.width / desiredCurve!
let bounds: CGRect = self.bounds
let rectBounds: CGRect = CGRect(x: bounds.origin.x, y: bounds.origin.y + bounds.size.height / 2, width: bounds.size.width, height: bounds.size.height / 2)
let rectPath: UIBezierPath = UIBezierPath(rect: rectBounds)
let ovalBounds: CGRect = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width: bounds.size.width + offset, height: bounds.size.height)
let ovalPath: UIBezierPath = UIBezierPath(ovalIn: ovalBounds)
rectPath.append(ovalPath)
// Create the shape layer and set its path
let maskLayer: CAShapeLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.path = rectPath.cgPath
// Set the newly created shape layer as the mask for the view's layer
self.layer.mask = maskLayer
}
}
答案 1 :(得分:1)
重新发布我在另一个帖子上发布的答案:
我现在可以确认这是iOS 6之后引入的一个错误。我有一个运行iOS 6.1的旧4。在那台机器上,这段代码:
path = [UIBezierPath bezierPathWithRoundedRect: bounds
byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight
cornerRadii: CGSizeMake(bounds.size.width/2, bounds.size.width/6)
];
创建一个圆角矩形,其边角为椭圆形。曲线顶部的曲线更加渐进,两侧更加锐利,如您所料:
这是iOS 6.1图片,应该是角落:
以下是从iOS 8.1.2运行时的相同代码:
似乎在iOS> = 7.0时,它会忽略指定半径的高度,并使用角度椭圆的高度和宽度的宽度值,这会强制它们始终为四分之一圆。
我在苹果的bug报告系统上记录了一个错误。我们会看到他们说的话。 我建议所有看到此问题的人也报告错误。他们获得的报告越多,就越有可能修复它。
(忽略底部的UISwitch。这是之前的测试遗留下来的。)
编辑:我编写的代码构建了一条贝塞尔曲线,大致近似于iOS生成的曲线的外观< 7.我刚刚找到article on approximating circles with bezier curves。使用该文章中的控制点,构建我们自己的等效于适用于所有iOS版本的bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
方法并不困难。
答案 2 :(得分:1)
执行此操作(或正确方法之一)的正确方法是使用UIBezierCurve
' s addQuadCurveToPoint:controlPoint
。您可以从路径到点的任何位置绘制二次曲线,使用另一个点作为控制点,这是一种确定结果路径将具有多少弧和曲线的方法。不要忘记,如果您使用图层作为蒙版,您还必须绘制形状的矩形部分,否则蒙版将只是曲线。
答案 3 :(得分:0)
有一次我在SO的某处发现了这个。它很棒。这是代码:
-(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 = (bl ? UIRectCornerBottomLeft : 0) | (br ? UIRectCornerBottomRight : 0) | (tl ? UIRectCornerTopLeft : 0) | (tr ? UIRectCornerTopRight : 0);
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;
} else {
return view;
}
}
让您的视图名称为_tView,然后调用:
_tView = (UIView *)[self roundCornersOnView:_tView onTopLeft:YES topRight:YES bottomLeft:NO bottomRight:NO radius:25.0];
这将给出如下输出:
答案 4 :(得分:0)
在故事板中还有一种简单的方法可以做到这一点。
答案 5 :(得分:0)
覆盖UIView类的绘制方法。
用于弯曲的上边缘
override func draw(_ rect: CGRect) {
let y:CGFloat = 20
let curveTo:CGFloat = 0
let myBezier = UIBezierPath()
myBezier.move(to: CGPoint(x: 0, y: y))
myBezier.addQuadCurve(to: CGPoint(x: rect.width, y: y), controlPoint: CGPoint(x: rect.width / 2, y: curveTo))
myBezier.addLine(to: CGPoint(x: rect.width, y: rect.height))
myBezier.addLine(to: CGPoint(x: 0, y: rect.height))
myBezier.close()
let context = UIGraphicsGetCurrentContext()
context!.setLineWidth(4.0)
//UIColor.white.setFill()
backgroundColor?.setFill()
myBezier.fill()
let maskLayer: CAShapeLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.path = myBezier.cgPath
self.layer.mask = maskLayer
}
用于弯曲的底边
override func draw(_ rect: CGRect) {
let y:CGFloat = 15
let curveTo:CGFloat = 0
let myBezier = UIBezierPath()
myBezier.move(to: CGPoint(x: 0, y: rect.height - y ))
myBezier.addQuadCurve(to: CGPoint(x: rect.width, y: rect.height - y), controlPoint: CGPoint(x: rect.width / 2, y: rect.height))
myBezier.addLine(to: CGPoint(x: rect.width, y: 0))
myBezier.addLine(to: CGPoint(x: 0, y: 0))
myBezier.close()
let context = UIGraphicsGetCurrentContext()
context!.setLineWidth(4.0)
//UIColor.white.setFill()
backgroundColor?.setFill()
myBezier.fill()
let maskLayer: CAShapeLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.path = myBezier.cgPath
self.layer.mask = maskLayer
}