Search code examples
iosswiftswift3radial-gradients

Radial Gradience Colors Not Updating in UIView


I am attempting to use radial gradience within my app on a background UIView. My issue comes to play, where I want to update the view colors of the gradience multiple times. I have no errors with my code, but I can't seem to figure out how to get around this.

What I have tried is reloading the Input Views within the regular UIView as-well as the gradience class; remove the subview of the uiview, and adding a new view to the screen, which worked for only change of set colors; and I have looked over the internet, but can't seem to resolve this. All I want is for the UIView to update its colors based on the new color parameters I give it.

Here is my radial gradience code:

import UIKit

class RadialGradient: UIView {


    var innerColor = UIColor.yellow
    var outterColor = UIColor.red

    override func draw(_ rect: CGRect) {

        let colors = [innerColor.cgColor, outterColor.cgColor] as CFArray
        let endRadius = min(frame.width, frame.height)

        let center = CGPoint(x: bounds.size.width/2, y: bounds.size.height/2)

        let gradient = CGGradient(colorsSpace: nil, colors: colors, locations: nil)

        UIGraphicsGetCurrentContext()!.drawRadialGradient(gradient!,
            startCenter: center,
            startRadius: 0.0,
            endCenter: center,
            endRadius: endRadius,
            options: CGGradientDrawingOptions.drawsAfterEndLocation)


    }

}

Here is where I am using it:

import UIKit

class TestIssuesVC: UIViewController {

    var check : Bool = false

    @IBAction func buttonClicked(_ sender: Any) {

        if check == true {
            backgroundsetting.removeFromSuperview()
            print("Why wont you change to purple and black?????")
            cheapFix(inner: UIColor.purple, outter: UIColor.black)

        } else {

        backgroundsetting.removeFromSuperview()

        cheapFix(inner: UIColor.red, outter: UIColor.blue)
            check = true
        }
    }

    func cheapFix(inner: UIColor, outter: UIColor) {

        let backgroundsetting = RadialGradient()

        backgroundsetting.innerColor = inner
        backgroundsetting.outterColor = outter

        backgroundsetting.frame = (frame: CGRect(x: self.view.frame.size.width * 0, y: self.view.frame.size.height * 0, width:self.view.frame.size.width, height: self.view.frame.size.height))
        self.view.addSubview(backgroundsetting)
        self.view.sendSubview(toBack: backgroundsetting)
        self.reloadInputViews()




    }
    let backgroundsetting = RadialGradient()


    override func viewWillAppear(_ animated: Bool) {
        backgroundsetting.innerColor = UIColor.green
        backgroundsetting.outterColor = UIColor.red

        backgroundsetting.frame = (frame: CGRect(x: self.view.frame.size.width * 0, y: self.view.frame.size.height * 0, width:self.view.frame.size.width, height: self.view.frame.size.height))
        self.view.addSubview(backgroundsetting)
        self.view.sendSubview(toBack: backgroundsetting)
        self.reloadInputViews()

    }


}

Solution

  • I see two things.

    1. Your cheapFix method never updates the backgroundsetting property. It creates its own local variable of the same name. So you are actually adding new views over and over but each is sent to the back so you only ever see the first one. This is why nothing ever appears to change.
    2. None of that is necessary. Simply create one RadialGradient view. When you want its colors to change, simply update its colors. That class needs to be fixed so it redraws itself when its properties are updated.

    Make the following change to the two properties in your RadialGradient class:

    var innerColor = UIColor.yellow {
        didSet {
            setNeedsDisplay()
        }
    }
    var outterColor = UIColor.red {
        didSet {
            setNeedsDisplay()
        }
    }
    

    Those changes will ensure the view redraws itself when its colors are updated.