Search code examples
iosswiftautolayoutcagradientlayer

Applying gradient colour to storyboard view with auto layout


I have added a UIView in the storyboard and want to set its background with gradient colors. This is my code

extension UIView {
    func setGradientBackground(colors: [CGColor]) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = colors
        gradientLayer.locations = [0.0, 1.0]
        gradientLayer.frame = self.bounds
        self.layer.insertSublayer(gradientLayer, at:0)
    }
}

and in the viewcontroller,

viewSocial.setGradientBackground(colors: [UIColor.gradientBottomColor.cgColor, UIColor.gradientTopColor.cgColor])

But this creates double gradient layers. see the image

I have tried adding a class for GradientLayer as mentioned here. But this is not allowing to set on a view from the storyboard. Gives the warning of the weak variable.


Solution

  • Here is one way to make a @IBDesignable gradient view. It's using the default top-to-bottom gradient direction:

    @IBDesignable
    class MyGradientView: UIView {
        
        @IBInspectable var color1: UIColor = .red {
            didSet { setNeedsDisplay() }
        }
        @IBInspectable var color2: UIColor = .yellow {
            didSet { setNeedsDisplay() }
        }
    
        private var gradientLayer: CAGradientLayer!
        
        override class var layerClass: AnyClass {
            return CAGradientLayer.self
        }
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        func commonInit() -> Void {
            // use self.layer as the gradient layer
            gradientLayer = self.layer as? CAGradientLayer
            gradientLayer.colors = [color1.cgColor, color2.cgColor]
        }
        
        override func layoutSubviews() {
            super.layoutSubviews()
            
            gradientLayer.colors = [color1.cgColor, color2.cgColor]
        }
        
    }
    

    It has @IBInspectable vars for "color1" and "color2" ... changing them in the Attributes Inspector will be reflected in Storyboard.

    No need for any additional code, such as your current approach with setGradientBackground()