简体   繁体   中英

Drawing Shape layer using Coregraphics - iOS

I am trying to achieve following shape using coregraphics.

卡片视图

I am able to create a rounded rect

func createRoundedRect() {
          let path = UIBezierPath(roundedRect: self.bounds, cornerRadius: 15.0)

            // Specify the point that the path should start get drawn.
           path.move(to: CGPoint(x: 0.0, y: 0.0))

           // Create a line between the starting point and the bottom-left side of the view.
           path.addLine(to: CGPoint(x: 0.0, y: self.frame.size.height))

           // Create the bottom line (bottom-left to bottom-right).
           path.addLine(to: CGPoint(x: self.frame.size.width, y: self.frame.size.height))

           // Create the vertical line from the bottom-right to the top-right side.
           path.addLine(to: CGPoint(x: self.frame.size.width, y: 0.0))

           // Close the path. This will create the last line automatically.
           path.close()
    }

But I am not sure how to make a view of above shape. Any help or idea is appreciated.

You render this with just two arcs, one for the top and one for the bottom. Just use a fat lineWidth and set the strokeColor to be the same as the fillColor to achieve the desired corner radius.

For example:

@IBDesignable
class TvView: UIView {
    override class var layerClass: AnyClass { CAShapeLayer.self }
    var shapeLayer: CAShapeLayer { return layer as! CAShapeLayer}

    @IBInspectable var curveHeight:  CGFloat = 10 { didSet { setNeedsLayout() } }
    @IBInspectable var cornerRadius: CGFloat = 10 { didSet { setNeedsLayout() } }

    override func layoutSubviews() {
        super.layoutSubviews()
        shapeLayer.fillColor = UIColor.red.cgColor
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.path = path()?.cgPath
        shapeLayer.lineWidth = cornerRadius * 2
        shapeLayer.lineJoin = .round
    }

    func path() -> UIBezierPath? {
        let rect = bounds.insetBy(dx: cornerRadius, dy: cornerRadius)

        guard
            rect.height > 2 * curveHeight,
            rect.width > 0,
            curveHeight > 0
        else {
            return nil
        }

        let angle: CGFloat = 2 * (atan2(curveHeight, rect.width / 2))
        let radius = rect.width / 2 / sin(angle)
        let path = UIBezierPath(arcCenter: CGPoint(x: rect.midX, y: rect.minY + radius), radius: radius, startAngle: .pi * 3 / 2 - angle, endAngle: .pi * 3 / 2 + angle, clockwise: true)
        path.addArc(withCenter: CGPoint(x: rect.midX, y: rect.maxY - radius), radius: radius, startAngle: .pi / 2 - angle, endAngle: .pi / 2 + angle, clockwise: true)
        path.close()
        return path
    }
}

Using the same color for stroke and fill, that yields:

在此处输入图片说明

Or, so you can see what's going on, here it is with the stroke rendered in a different color:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM