class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let g = view.safeAreaLayoutGuide let gv = Gradient() gv.translatesAutoresizingMaskIntoConstraints = false view.addSubview(gv) NSLayoutConstraint.activate([ gv.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0), gv.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0), gv.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0), gv.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0), ]) //gv.diagonalMode = true //gv.horizontalMode = true view.backgroundColor = .systemYellow } } class Gradient: UIView { var startColor: UIColor = .white { didSet { updateColors() }} var endColor: UIColor = .red { didSet { updateColors() }} var horizontalMode: Bool = false { didSet { updatePoints() }} var diagonalMode: Bool = false { didSet { updatePoints() }} override class var layerClass: AnyClass { CAGradientLayer.self } var gradientLayer: CAGradientLayer { layer as! CAGradientLayer } override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } private func commonInit() { updatePoints() updateLocations() updateColors() } func updatePoints() { if horizontalMode { gradientLayer.startPoint = diagonalMode ? .init(x: 1, y: 0) : .init(x: 0, y: 0.5) gradientLayer.endPoint = diagonalMode ? .init(x: 0, y: 1) : .init(x: 1, y: 0.5) } else { gradientLayer.startPoint = diagonalMode ? .init(x: 0, y: 0) : .init(x: 0.5, y: 0) gradientLayer.endPoint = diagonalMode ? .init(x: 1, y: 1) : .init(x: 0.5, y: 1) } } func updateLocations() { gradientLayer.locations = [0, 0.5, 0.5, 1.0] } func updateColors() { gradientLayer.colors = [startColor.cgColor, startColor.cgColor, endColor.cgColor, endColor.cgColor] } }