Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CAGradientLayer does not display

I have looked over a bunch of other answers to questions like this, but none of the answers seem to solve my problem, so looking for a little help.

I'm trying to apply a vertical gradient to a UIButton, but the gradient layer is just not showing up in my view. Here is the relevant code:

let darkPurple = UIColor(displayP3Red: 61.0/255.0, green: 3.0/255.0, blue: 110.0/255.0, alpha: 1.0)
let lightPurple = UIColor(displayP3Red: 90.0/255.0, green: 32.0/255.0, blue: 130.0/255.0, alpha: 1.0)

let addButton = UIButton(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
addButton.title = "Start counting"
addButton.layer.cornerRadius = 30.0
addButton.layer.borderWidth = 1.0
addButton.layer.borderColor = darkPurple.cgColor
addButton.translatesAutoresizingMaskIntoConstraints = false
myView.addSubview(addButton)
addButton.applyGradient(with: [lightPurple, darkPurple], gradientOrientation: .vertical)

...and the code to apply the gradient:

typealias GradientPoints = (startPoint: CGPoint, endPoint: CGPoint)

enum GradientOrientation {
  case topRightBottomLeft
  case topLeftBottomRight
  case horizontal
  case vertical

  var startPoint: CGPoint {
    return points.startPoint
  }

  var endPoint: CGPoint {
    return points.endPoint
  }

  var points: GradientPoints {
    switch self {
    case .topRightBottomLeft:
      return (CGPoint(x: 0.0, y: 1.0), CGPoint(x: 1.0, y: 0.0))
    case .topLeftBottomRight:
      return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 1.0, y: 1.0))
    case .horizontal:
      return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 1.0, y: 0.0))
    case .vertical:
      return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 0.0, y: 1.0))
    }
  }
}

extension UIView {
  func applyGradient(with colors: [UIColor], gradientOrientation orientation: GradientOrientation) {
    let gradient = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.colors = colors.map { $0.cgColor }
    gradient.startPoint = orientation.startPoint
    gradient.endPoint = orientation.endPoint
    gradient.borderColor = self.layer.borderColor
    gradient.borderWidth = self.layer.borderWidth
    gradient.cornerRadius = self.layer.cornerRadius
    gradient.masksToBounds = true
    gradient.isHidden = false

    self.layer.insertSublayer(gradient, at: 0)
  }
}

This is what I get: empty button

Thanks for your help!

like image 291
kyanring Avatar asked Aug 23 '26 07:08

kyanring


1 Answers

For anyone who already spent hours of searching (like I did):

Make sure, that your colors array contains CGColor instead of UIColor, as per docs:

colors

An array of CGColorRef objects defining the color of each gradient stop. Animatable.

https://developer.apple.com/documentation/quartzcore/cagradientlayer/1462403-colors

Bonus: this little code snippet will crash app, if you miss it again (using #if DEBUG is recommended)

extension CAGradientLayer {
    dynamic var colors: [Any]? {
        get { self.value(forKey: "colors") as? [Any] }
        set {
            if let newValue = newValue {
                for color in newValue {
                    if color is UIColor {
                        fatalError("CAGradientLayer.colors must contain only CGColor! UIColor was found")
                    }
                }
            }
            super.setValue(newValue, forKey: "colors")
        }
    }
}
like image 176
Dima Rostopira Avatar answered Aug 25 '26 22:08

Dima Rostopira



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!