Mike
Mike

Reputation: 53

Gradient Colors not changing based on Button isSelected State

I made a custom gradient Button, such that I can change the gradient color on different states:

class GradientButton: UIButton {

public var buttongradient: CAGradientLayer = CAGradientLayer()

override var isSelected: Bool {
    didSet {
        if isSelected {
            buttongradient.colors = [UIColor(hexString: "#ef473a")!, UIColor(hexString: "#cb2d3e")!].map { $0.cgColor }
        } else {
            buttongradient.colors = [UIColor(hexString: "#29a1e2")! , UIColor(hexString: "#485ac8")!].map { $0.cgColor }
        }
    }
}

override init(frame: CGRect) {
    super.init(frame: frame)
    self.addthegradientLayer()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.addthegradientLayer()
}

override func layoutSubviews() {
    super.layoutSubviews()
    self.addthegradientLayer()

}

func addthegradientLayer() {
    //the cells gradient colors
    buttongradient.frame = self.bounds
    buttongradient.cornerRadius = buttongradient.frame.height / 2
    buttongradient.colors = [UIColor(hexString: "#29a1e2")! , UIColor(hexString: "#485ac8")!].map { $0.cgColor }
    buttongradient.startPoint = CGPoint(x: 1.0, y: 0.0)
    buttongradient.endPoint = CGPoint(x: 0.0, y: 1.0)
    self.layer.insertSublayer(buttongradient, at: 0)
}

When I run this code, the button background is clear. No Gradient showing.

EDIT

As in the comments suggested:

buttongradient.frame = self.bounds

is the solution.

Follow up Problem

Now I realise, that the gradient does not change colors based on the isSelected state.

Upvotes: 0

Views: 552

Answers (1)

Sulthan
Sulthan

Reputation: 130102

There are multiple problems:

  1. As you already now, you have to use self.bounds to update the layer frame.
  2. Changing the layer in initializers is not necessary. The layoutSubviews is always called before rendering.
  3. If your aim is to change colors when the button is pressed, you want to use isHighlighted, not isSelected.
  4. Every layout will rewrite your color values, remove buttongradient.colors from the layout method.
  5. There is no need to use strings for hexadecimal color definition. I would recommend to use integers, e.g. 0x29a1e2 (see How to use hex colour values).
class GradientButton: UIButton {

    public let buttongradient: CAGradientLayer = CAGradientLayer()

    override var isSelected: Bool {  // or isHighlighted?
        didSet {
            updateGradientColors()
        }
    }

    func updateGradientColors() {
        let colors: [UIColor]

        if isSelected {
           colors = [UIColor(hexString: "#ef473a")!, UIColor(hexString: "#cb2d3e")!]
        } else {
           colors = [UIColor(hexString: "#29a1e2")!, UIColor(hexString: "#485ac8")!]
        }

        buttongradient.colors = colors.map { $0.cgColor }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setupGradient()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.setupGradient()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.updateGradient()
    }

    func setupGradient() {
        buttongradient.startPoint = CGPoint(x: 1.0, y: 0.0)
        buttongradient.endPoint = CGPoint(x: 0.0, y: 1.0)
        self.layer.insertSublayer(buttongradient, at: 0)

        updateGradientColors()
    }

    func updateGradient() {
        buttongradient.frame = self.bounds
        buttongradient.cornerRadius = buttongradient.frame.height / 2
    }
}

Upvotes: 1

Related Questions