I wanted to provide a code sample using Swift 5 on how to implement it in a UIViewController
all using programmatic UI with UIKit
. The key component for me that I missed was that where you create a CAShapeLayer
and add it to a view's layer, it must be called in either layoutSubviews()
if you're doing in a UIView
or viewDidLayoutSubviews()
if you're creating the shape within the UIViewController
. You'll need to familiarize yourself with how to use UIBezierPath
to understand the drawing mechanics.
Here are the resources I found to be most useful:
Apple Docs on UIBezierPath
Medium Blog write up on UIBezierPath
import UIKit
class ViewController: UIViewController {
var diagonalSideView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .black
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
makeDiagonalDividerShape(from: diagonalSideView)
}
private func setupViews() {
view.addSubview(diagonalSideView)
let heightConstraint = diagonalSideView.heightAnchor.constraint(equalToConstant: 200)
let leftConstraint = diagonalSideView.leftAnchor.constraint(equalTo: view.leftAnchor)
let rightConstraint = diagonalSideView.rightAnchor.constraint(equalTo: view.rightAnchor)
let centerXConstraint = diagonalSideView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let centerYConstraint = diagonalSideView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([heightConstraint,
leftConstraint,
rightConstraint,
centerXConstraint,
centerYConstraint])
}
private func makeDiagonalDividerShape(from view: UIView) {
let layer = CAShapeLayer()
// Create Path
let bezierPath = UIBezierPath()
// Points of the Polygon with Diagonal left side
let pointA = CGPoint(x: view.bounds.origin.x, y: view.bounds.height)
let pointB = CGPoint(x: view.bounds.width / 4, y: view.bounds.origin.y)
let pointC = CGPoint(x: view.bounds.width, y: view.bounds.origin.y)
let pointD = CGPoint(x: view.bounds.width, y: view.bounds.height)
// Draw the path
bezierPath.move(to: pointA)
bezierPath.addLine(to: pointB)
bezierPath.addLine(to: pointC)
bezierPath.addLine(to: pointD)
bezierPath.close()
// Create the mask
layer.path = bezierPath.cgPath
view.layer.mask = layer
}
}
Final result:
