How to create unique shapes or UIViews in Swift

Caleb's answer updated to Swift 5:

class PentagonView : UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .clear
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        backgroundColor = .clear
    }

    override func draw(_ rect: CGRect) {
        let size = self.bounds.size
        let h = size.height * 0.85      // adjust the multiplier to taste

        // calculate the 5 points of the pentagon
        let p1 = self.bounds.origin
        let p2 = CGPoint(x:p1.x + size.width, y:p1.y)
        let p3 = CGPoint(x:p2.x, y:p2.y + h)
        let p4 = CGPoint(x:size.width/2, y:size.height)
        let p5 = CGPoint(x:p1.x, y:h)

        // create the path
        let path = UIBezierPath()
        path.move(to: p1)
        path.addLine(to: p2)
        path.addLine(to: p3)
        path.addLine(to: p4)
        path.addLine(to: p5)
        path.close()

        // fill the path
        UIColor.red.set()
        path.fill()
    }
}

Can I make this shape/UIView in Swift by code? And if so, how?

Views are always rectangular, but a view's content can be any shape at all and it's background can be transparent, so the visible part of a view can be anything you can draw.

There are a lot of ways to draw something in iOS. It's usually best to start with the highest level tool that'll work for you and move down to a lower level when you need more control. With that in mind, I'd suggest starting by creating a view that draws your pentagon using a UIBezierPath. The (Swift 5) code for this is very simple:

class PentagonView : UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor.clear
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        backgroundColor = UIColor.clear
    }

    override func draw(_ rect: CGRect) {
        let size = self.bounds.size
        let h = size.height * 0.85      // adjust the multiplier to taste

        // calculate the 5 points of the pentagon
        let p1 = self.bounds.origin
        let p2 = CGPoint(x:p1.x + size.width, y:p1.y)
        let p3 = CGPoint(x:p2.x, y:p2.y + h)
        let p4 = CGPoint(x:size.width/2, y:size.height)
        let p5 = CGPoint(x:p1.x, y:h)

        // create the path
        let path = UIBezierPath()
        path.move(to: p1)
        path.addLine(to: p2)
        path.addLine(to: p3)
        path.addLine(to: p4)
        path.addLine(to: p5)
        path.close()

        // fill the path
        UIColor.red.set()
        path.fill()
    }
}

And now you can use that view anywhere in your UI: PentagonView

If you want to add a 150x150px PentagonView to your view controller's main view at coordinates (100, 200), you could put the following in viewDidLoad():

let pg = PentagonView(frame:CGRect(x:100, y:200, width:150, height:150))
self.view.addSubview(pg)

Or, you could also add a PentagonView to some view in your storyboard by dropping in a UIView of the right size and then changing it's class to PentagonView.

Or, is it better to just create this as an image and do it that way?

If you've fully described your requirement, then no, I don't think so: the image itself will probably be a lot larger than the code that draws it, and the code that I've given above will work at any size you choose. On the other hand, if you're going to add a lot of complex detail, and if the image only needs to appear at one size, then it might be easier to create it once in a drawing program and store that work as an image. Like I said above, there are a lot of options for drawing in iOS; which you choose should be determined by your needs.

Tags:

Ios

Uiview

Swift