Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CAShapeLayer with UIBezierPath

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?

like image 532
Isuru Avatar asked Apr 06 '15 17:04

Isuru


People also ask

What is UIBezierPath?

A UIBezierPath object combines the geometry of a path with attributes that describe the path during rendering. You set the geometry and attributes separately and can change them independent of one another. After you have the object configured the way you want it, you can tell it to draw itself in the current context.

What is CAShapeLayer?

A layer that draws a cubic Bezier spline in its coordinate space.


2 Answers

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)
    }
}
like image 97
rdelmar Avatar answered Sep 17 '22 09:09

rdelmar


The problem should be the mask on layer and the color of shape.
The following code work for me.

class TriangleView: UIView {
    override func drawRect(rect: CGRect) {
        let width:CGFloat = bounds.width/9
        let height:CGFloat = bounds.width/9

        let path = UIBezierPath()
        path.moveToPoint(bounds.origin)
        path.addLineToPoint(CGPoint(x: width, y: bounds.origin.y))
        path.addLineToPoint(CGPoint(x: bounds.origin.x, y: height))
        // closePath will connect back to start point
        path.closePath()

        let shape = CAShapeLayer()
        shape.path = path.CGPath
        shape.fillColor = UIColor.blueColor().CGColor

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

        // Setting text margin
        textContainerInset = UIEdgeInsetsMake(8, width, 8, 0)
    }
}
like image 27
chiahao Avatar answered Sep 20 '22 09:09

chiahao