CAShapeLayer with UIBezierPath

Isuru picture Isuru · Apr 6, 2015 · Viewed 8.1k times · Source

I wanted to display a triangle shaped view in a UITableView cell like this.

enter image description here

I managed to accomplish this using the blow code.

import UIKit

class TriangleView: UIView {

    override func drawRect(rect: CGRect) {
        let width = self.layer.frame.width
        let height = self.layer.frame.height

        let path = CGPathCreateMutable()
        CGPathMoveToPoint(path, nil, 0, 0)
        CGPathAddLineToPoint(path, nil, width, 0)
        CGPathAddLineToPoint(path, nil, 0, height)
        CGPathAddLineToPoint(path, nil, 0, 0)
        CGPathCloseSubpath(path)

        let mask = CAShapeLayer()
        mask.frame = self.layer.bounds
        mask.path = path

        self.layer.mask = mask

        let shape = CAShapeLayer()
        shape.frame = self.bounds
        shape.path = path
        shape.fillColor = UIColor.clearColor().CGColor

        self.layer.insertSublayer(shape, atIndex: 0)
    }
}

While I was searching how to create shapes in UIViews, I discovered that you could use UIBezierPath to do the same. So I tried replicating the same thing using UIBezierPath.

let path = UIBezierPath()
path.moveToPoint(CGPoint(x: 0, y: 0))
path.moveToPoint(CGPoint(x: width, y: 0))
path.moveToPoint(CGPoint(x: 0, y: height))
path.moveToPoint(CGPoint(x: 0, y: 0))
path.closePath()

let mask = CAShapeLayer()
mask.frame = self.bounds
mask.path = path.CGPath

self.layer.mask = mask

let shape = CAShapeLayer()
shape.frame = self.bounds
shape.path = path.CGPath
shape.fillColor = UIColor.clearColor().CGColor

self.layer.insertSublayer(shape, atIndex: 0)

But this simply does't work. No shape is getting displayed.

Do I need to do anything extra in order to get this working?

Answer

rdelmar picture rdelmar · Apr 6, 2015

You're making this harder than it needs to be. You only need to add a shape layer with a path, and set the fillColor of that layer. The main reason your code doesn't work though, is because you're using moveToPoint for all you lines instead of addLineToPoint for all but the first one.

class TriangleView: UIView {

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        let path = UIBezierPath()
        path.moveToPoint(CGPoint(x: 0, y: 0))
        path.addLineToPoint(CGPoint(x: frame.size.width, y: 0))
        path.addLineToPoint(CGPoint(x: 0, y: frame.size.height))
        path.closePath()

        let shape = CAShapeLayer()
        shape.frame = self.bounds
        shape.path = path.CGPath
        shape.fillColor = UIColor.blueColor().CGColor
        self.layer.addSublayer(shape)
    }
}