创建一个圆顶边的UIView

时间:2015-01-18 02:31:40

标签: ios objective-c uibezierpath bezier

我想创建一个带有圆顶边的UIView,就像这张图片一样,我该怎么办呢?

通缉结果

Wanted

不想要的结果

Not wanted

6 个答案:

答案 0 :(得分:2)

Image

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图片,应该是角落: This is the iOS 6.1 image, with the corners as they should be

以下是从iOS 8.1.2运行时的相同代码: enter image description here

似乎在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)

enter image description here

有一次我在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)

在故事板中还有一种简单的方法可以做到这一点。

  1. 创建一个没有背景颜色的UIView(clearColor)。
  2. 在此视图中,使用您需要的bg颜色创建另外两个视图。
  3. 将一个视图放在另一个视图的顶部,转到右侧面板中的Identity Inspector。并在“用户定义的运行时属性”部分中添加“layer.cornerRadius = desiredRadius ”。
  4. 您现在有两个bg颜色的视图。一个圆角和一个没有,只需调整它们的位置,以实现你所追求的外观,就是这样。无需编码。

答案 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

        }