Usually, viewDidLoad
for view controllers or init
for custom views is too early for gradient frames. Also, their frames will most likely change later on, which you need to handle.
If you are applying a gradient to a custom view, try updating its frame inside layoutSubviews()
(from this great answer).
class GradientButton: UIButton {
/// update inside layoutSubviews
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = bounds
}
private lazy var gradientLayer: CAGradientLayer = {
let l = CAGradientLayer()
l.frame = self.bounds
l.colors = [UIColor.systemYellow.cgColor, UIColor.systemPink.cgColor]
l.startPoint = CGPoint(x: 0, y: 1)
l.endPoint = CGPoint(x: 0, y: )
layer.insertSublayer(l, at: 0)
return l
}()
}
For a view in a view controller, try viewDidLayoutSubviews()
.
class ViewController: UIViewController {
@IBOutlet weak var addToCart: UIButton!
var gradientLayer: CAGradientLayer? /// keep a reference to the gradient layer so we can update its frame later
override func viewDidLoad() {
super.viewDidLoad()
/// still first make the gradient inside viewDidLoad
applyGradient(colors: [UIColor.systemYellow.cgColor, UIColor.systemPink.cgColor])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
/// update here!
self.gradientLayer?.frame = self.addToCart.bounds
}
private func applyGradient(colors: [CGColor]) {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = colors
gradientLayer.startPoint = CGPoint(x: 0, y: 1)
gradientLayer.endPoint = CGPoint(x: 0, y: 0)
gradientLayer.frame = self.addToCart.bounds
self.addToCart.layer.insertSublayer(gradientLayer, at: 0)
self.gradientLayer = gradientLayer
}
}