How to continually change gradient color background?

1.1k Views Asked by At

I currently have a single gradient color background (see below), but I want to gradually change the colors to shades that I will pre-define in an array and have it loop through. How can I achieve this?

var colorTop =  UIColor(red: 255.0/255.0, green: 149.0/255.0, blue: 0.0/255.0, alpha: 1.0).cgColor
var colorBottom = UIColor(red: 255.0/255.0, green: 94.0/255.0, blue: 58.0/255.0, alpha: 1.0).cgColor

func configureGradientBackground(colors:CGColor...){
    let gradient: CAGradientLayer = CAGradientLayer()
    let maxWidth = max(self.view.bounds.size.height,self.view.bounds.size.width)
    gradient.startPoint = CGPoint(x: 0, y: 0)
    gradient.endPoint = CGPoint(x: 1, y: 1)

    let squareFrame = CGRect(origin: self.view.bounds.origin, size: CGSize(width: maxWidth, height: maxWidth * 0.935))
    gradient.frame = squareFrame

    gradient.colors = colors
    view.layer.insertSublayer(gradient, at: 0)
}

override func viewDidLoad() {
    super.viewDidLoad()
    configureGradientBackground(colors: colorTop, colorBottom)
}
2

There are 2 best solutions below

6
On

You could have a variable in your viewDidLoad that is an int that keeps track of the index of the array that contains all your colors. For example, 0 is your first color, 1 is your second and so on. Then in your infinite while loop (also in the viewDidLoad), you can write:

if tracker == 0 {
   // apply first color
} else if tracker == 1{
   // apply second color
} ...

Then you can increment the tracker by one at the end and then check your if your tracker is past the size of your array (for example, you only have 11 colors).

tracker += 1
if tracker > 10 {
   tracker = 0
}
0
On

Really quite straightforward; I can't imagine what difficulty you are having. CAGradientLayer's colors property is itself animatable, so you simply animate the change of colors and, when the animation ends, proceed to the next animation of the change of colors.

In this example I alternate between just two sets of colors, yours and blue-and-green. So my state is a simple Bool. But obviously the example could be extended to any number of states, that is, any number of pairs of colors.

let colorTop =  UIColor(red: 255.0/255.0, green: 149.0/255.0, blue: 0.0/255.0, alpha: 1.0).cgColor
let colorBottom = UIColor(red: 255.0/255.0, green: 94.0/255.0, blue: 58.0/255.0, alpha: 1.0).cgColor
var state = false
var grad : CAGradientLayer?
override func viewDidLoad() {
    // configure the gradient layer, start the animation        
}
func animate() {
    let arr = self.state ? [colorTop,colorBottom] : [UIColor.green.cgColor,UIColor.blue.cgColor]
    self.state = !self.state
    let anim = CABasicAnimation(keyPath: "colors")
    anim.duration = 10 // or whatever
    anim.fromValue = self.grad!.colors
    anim.toValue = arr
    anim.delegate = self
    self.grad?.add(anim, forKey: nil)
    DispatchQueue.main.async {
        CATransaction.setDisableActions(true)
        self.grad?.colors = arr
    }
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
    DispatchQueue.main.async {
        self.animate()
    }
}