wayneh
wayneh

Reputation: 4413

Change colors in a CAGradientLayer after inserting

I have a class function to create a CAGradient layer and insert it to a UIView which works fine.

However, I'd like to modify the gradient after the page is shown, and re-executing the same function does not work.

On the displayed page I use sliders to set new colors into two UIButton backgrounds, and call the function below. I'm expecting the gradient layer background to change when I change the slider but it doesn't. I've verified that the function is being called and the color values are valid.

How can I change the gradient as I move the sliders?

Here's the class function:

class func setGradientBG(_ firstColor: CGColor, secondColor: CGColor, vertical: Bool, thisView: UIView){
    let gradientLayer = CAGradientLayer()
    gradientLayer.frame = thisView.bounds
    gradientLayer.colors = [firstColor, secondColor]
    gradientLayer.locations = [0.0, 1.2]
    if !vertical{
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
    }
    thisView.layer.insertSublayer(gradientLayer, at: 0)
}

And here's the function called from the sliders:

func doSlider(){
   CommonFuncs.setGradientBG((self.TopColorBut.backgroundColor?.cgColor)!,  secondColor: (self.BottomColorBut.backgroundColor?.cgColor)!, vertical: true, thisView: self.view)
}

Upvotes: 1

Views: 1585

Answers (2)

rob mayoff
rob mayoff

Reputation: 386018

You're adding another instance of CAGradientLayer every time you call setGradientBG. Do you really think that's a good idea?

It looks like your doSlider method is probably part of a custom UIViewController subclass. What you should do is store a reference to the gradient layer in the view controller, and update that existing layer. Example:

class ViewController: UIViewController {

    private let gradientLayer = CAGradientLayer()

    @IBOutlet var topColorButton: UIButton!
    @IBOutlet var bottomColorButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        view.layer.insertSublayer(gradientLayer, at: 0)
        self.updateGradientLayer()
    }

    @IBAction func doSlider() {
        updateGradientLayer()
    }

    private func updateGradientLayer() {
        gradientLayer.locations = [ 0.0, 1.2 ]
        gradientLayer.startPoint = .zero
        gradientLayer.endPoint = CGPoint(x: 0, y: 1)
        gradientLayer.colors = [
            (topColorButton.backgroundColor ?? .clear).cgColor,
            (bottomColorButton.backgroundColor ?? .clear).cgColor ]
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        gradientLayer.frame = view.bounds
    }

}

Upvotes: 3

Lumialxk
Lumialxk

Reputation: 6379

Sublayers are listed in back to front order. So insert the new sublayer at last. Or remove old ones.

Upvotes: 0

Related Questions