Re-Animate Gradient Background with different color in swift on ios

I want to update the gradient background with a different color when animating. I can successfully change the gradient color with this code.

let dayTopColor = CommonUtils.colorWithHexString("955EAC") let dayBottomColor = CommonUtils.colorWithHexString("9F3050") let dayToTopColor = CommonUtils.colorWithHexString("D15B52") let dayToBottomColor = CommonUtils.colorWithHexString("CC4645") let nightTopColor = CommonUtils.colorWithHexString("2D5E7C") let nightBottomColor = CommonUtils.colorWithHexString("19337D") let nightToTopColor = CommonUtils.colorWithHexString("21334E") let nightToBottomColor = CommonUtils.colorWithHexString("101A55") var isInSaudiArabia = false var gradient : CAGradientLayer? var toColors : AnyObject? var fromColors : AnyObject? func animateBackground(){ var layerToRemove: CAGradientLayer? for layer in self.view.layer.sublayers!{ if layer.isKindOfClass(CAGradientLayer) { layerToRemove = layer as? CAGradientLayer } } layerToRemove?.removeFromSuperlayer() self.gradient!.colors = [nightTopColor.CGColor, nightBottomColor.CGColor] self.toColors = [nightToTopColor.CGColor, nightToBottomColor.CGColor] self.view.layer.insertSublayer(self.gradient!, atIndex: 0) animateLayer() } func animateLayer(){ self.fromColors = self.gradient!.colors! self.gradient!.colors = self.toColors as? [AnyObject] let animation : CABasicAnimation = CABasicAnimation(keyPath: "colors") animation.delegate = self animation.fromValue = fromColors animation.toValue = toColors animation.duration = 3.50 animation.removedOnCompletion = true animation.fillMode = kCAFillModeForwards animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) animation.delegate = self self.gradient!.addAnimation(animation, forKey:"animateGradient") } override func animationDidStop(anim: CAAnimation, finished flag: Bool) { self.toColors = self.fromColors; self.fromColors = self.gradient!.colors! animateLayer() } 

CommonUtils.colorWithHexString () is a function that converts hexadecimal color to UIColor. Btw, when I try to change the background color of the day during the animation, the background color of the gradient becomes flickering.

Is there anyone who knows the solution.

+6
source share
1 answer

The problem is that when the layer is deleted, it stops the animation. But when the animation stops, animationDidStop still raises a call that starts a new animation. So, you delete the layer that stops the animation, immediately starts another, but you start another animation. You have duel animations.

You can check the flag to make sure the animation is finished correctly before animationDidStop should call animateLayer .

 override func animationDidStop(anim: CAAnimation, finished flag: Bool) { if flag { toColors = fromColors; fromColors = gradient!.colors! animateLayer() } } 

Personally, I'm not sure why you delete and add and remove this layer. And if you were, I'm not sure why you are not just gradient?.removeFromSuperlayer() , and not iterating through layers.

Regardless of the fact that I just left the gradient layer, just check its presentationLayer and start the animation from there:

 class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() fromColors = [dayTopColor.CGColor, dayBottomColor.CGColor] toColors = [dayToTopColor.CGColor, dayToBottomColor.CGColor] gradient = CAGradientLayer() gradient!.colors = fromColors! gradient!.frame = view.bounds view.layer.addSublayer(gradient!) animateLayer() } let dayTopColor = CommonUtils.colorWithHexString("955EAC") let dayBottomColor = CommonUtils.colorWithHexString("9F3050") let dayToTopColor = CommonUtils.colorWithHexString("D15B52") let dayToBottomColor = CommonUtils.colorWithHexString("CC4645") let nightTopColor = CommonUtils.colorWithHexString("2D5E7C") let nightBottomColor = CommonUtils.colorWithHexString("19337D") let nightToTopColor = CommonUtils.colorWithHexString("21334E") let nightToBottomColor = CommonUtils.colorWithHexString("101A55") var gradient : CAGradientLayer? var toColors : [CGColor]? var fromColors : [CGColor]? var day = true func toggleFromDayToNight() { day = !day if day { fromColors = [dayTopColor.CGColor, dayBottomColor.CGColor] toColors = [dayToTopColor.CGColor, dayToBottomColor.CGColor] } else { fromColors = [nightTopColor.CGColor, nightBottomColor.CGColor] toColors = [nightToTopColor.CGColor, nightToBottomColor.CGColor] } let colors = (gradient!.presentationLayer() as! CAGradientLayer).colors // save the in-flight current colors gradient!.removeAnimationForKey("animateGradient") // cancel the animation gradient!.colors = colors // restore the colors to in-flight values animateLayer() // start animation } func animateLayer() { let animation : CABasicAnimation = CABasicAnimation(keyPath: "colors") animation.fromValue = gradient!.colors animation.toValue = toColors animation.duration = 3.50 animation.removedOnCompletion = true animation.fillMode = kCAFillModeForwards animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) animation.delegate = self gradient!.colors = toColors gradient!.addAnimation(animation, forKey:"animateGradient") } override func animationDidStop(anim: CAAnimation, finished flag: Bool) { if flag { swap(&toColors, &fromColors) animateLayer() } } @IBAction func didTapButton() { toggleFromDayToNight() } } 
+6
source

All Articles