-1

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 Answers2

1

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()
    }
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
0

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
}
kbunarjo
  • 1,277
  • 2
  • 11
  • 27
  • But doesn't that leave me with an issue of continually updating the colors? I've tried changing the gradient colors by calling the configureGradientBackground again with implementing new colors, but it doesnt update the colors; + I want to somehow animate the transition so that it is a clean changing of colors; any ideas? – Andrew Saxionis Dec 29 '16 at 04:15
  • [This](http://stackoverflow.com/questions/30380910/changing-uiview-background-color-using-an-animation) might help you with the animate part, for the rest then just loop infinite with `while` to change your color as the above answer suggest – Tj3n Dec 29 '16 at 05:25
  • But this doesnt update the colors; because when I call something to change the values of the gradient, it doesn't update the colors on the screen – Andrew Saxionis Dec 29 '16 at 19:21
  • For the infinite loop, you can use a timer object instead that has the appropriate function that updates the colors: https://www.weheartswift.com/nstimer-in-swift/ – kbunarjo Dec 30 '16 at 02:37
  • But how do i update the background color? in the example there it just updates it for a string, but for a background color isn't it different? – Andrew Saxionis Dec 30 '16 at 22:36
  • figured out how to reload with self.reloadInputViews() – Andrew Saxionis Dec 31 '16 at 21:13