Joe
Joe

Reputation: 3931

Swift - Using animateWithDuration to fade CAGradientLayer

I have switch statement controlling my background gradients. It works nicely (the gradients change), however it changes abruptly. I would like for these gradients to fade into each other with a .25 duration. My code attempt at this is below.

Switch statement that controls the backgrounds:

switch backgroundInput{
case 50...69:
self.view.configureGradient([gradientColor1, gradientColor2])
case 70...90:
self.view.configureGradient([gradientColor2, gradientColor3])
case 91...110:
self.view.configureGradient([gradientColor3, gradientColor4])
case 111...130:
self.view.configureGradient([gradientColor4, gradientColor5])
case 131...150:
self.view.configureGradient([gradientColor5, gradientColor6])
case 151...170:
self.view.configureGradient([gradientColor6, gradientColor7])
default:
self.view.configureGradient([lightPurple, lightBlue])
}

Extension that controls the gradients This is where I attempted the animate duration

extension UIView {
private func prepareGradient() -> CAGradientLayer {
    let gradientLayer = CAGradientLayer()
    gradientLayer.frame = self.bounds
    gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
    gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
    gradientLayer.zPosition = -1
    self.layer.addSublayer(gradientLayer)
    return gradientLayer
}
func configureGradient(colors:[CGColor]) {
    let gradientLayer = prepareGradient()
    UIView.animateWithDuration(0.25, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
        gradientLayer.colors = colors
        }, completion: nil)
}
}

How can I adjust my code above to fade the gradientlayers from one to another? (unrelated - is it bad for memory to constantly "add sublayer" on sublayers?)

Upvotes: 0

Views: 916

Answers (1)

Marco M
Marco M

Reputation: 1245

This will work:

func configureGradient(colors:[CGColor]) {
    let gradientLayer = prepareGradient()
    gradientLayer.colors = colors
    UIView.transitionWithView(self,
                              duration: 0.25,
                              options: UIViewAnimationOptions.TransitionCrossDissolve,
                              animations: { [weak self] () -> Void in
                                self?.layer.addSublayer(gradientLayer)
        }, completion: nil)
}

...anyway adding sublayers only to change color is not cool. Try to store your gradient layer in your extension:

private struct AssociatedKeys {
    static var gradientLayer = CAGradientLayer()
}

var gradientLayer: CAGradientLayer {
    get {
        guard let gLayer = objc_getAssociatedObject(self, &AssociatedKeys.gradientLayer) as? CAGradientLayer else { return CAGradientLayer() }
        return gLayer
    }
    set(value) {
        objc_setAssociatedObject(self, &AssociatedKeys.gradientLayer, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
}

May be a UIView subclass is more simple to implement... I think you should do it this way.

Upvotes: 3

Related Questions