Can I do it within the interface builder or do I have to do it programmatically?
You'll have to do this programmatically: Define the UIBezierPath
, using it as the path
of a CAShapeLayer
and then mask the view's layer using this shape layer.
@IBDesignable
class SlantedView: UIView {
@IBInspectable var slantHeight: CGFloat = 50 { didSet { updatePath() } }
private let shapeLayer: CAShapeLayer = {
let shapeLayer = CAShapeLayer()
shapeLayer.lineWidth = 0
shapeLayer.fillColor = UIColor.white.cgColor // with masks, the color of the shape layer doesn’t matter; it only uses the alpha channel; the color of the view is dictate by its background color
return shapeLayer
}()
override func layoutSubviews() {
super.layoutSubviews()
updatePath()
}
private func updatePath() {
let path = UIBezierPath()
path.move(to: bounds.origin)
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY - slantHeight))
path.close()
shapeLayer.path = path.cgPath
layer.mask = shapeLayer
}
}
But by making this an @IBDesignable
view, you can then render it in IB so you can at least design the UI with a greater sense of what the final product will look like:

FYI, if you do make this designable, they recommend that you create a separate framework target for your designables (so that if you go to IB while working on your main project, the ability to render the designable views isn't impacted by the fact that your main project may not be in a stable, compilable state).