iosswiftuibuttonibdesignable

how to set gradient layer width to be the same as button width?


I am new in iOS Development, I want to make gradient rounded button by using this designable class

@IBDesignable
class GradientButton: UIButton {
    let gradientLayer = CAGradientLayer()

    @IBInspectable
    var topGradientColor: UIColor? {
        didSet {
            setGradient(topGradientColor: topGradientColor, bottomGradientColor: bottomGradientColor)
        }
    }

    @IBInspectable
    var bottomGradientColor: UIColor? {
        didSet {
            setGradient(topGradientColor: topGradientColor, bottomGradientColor: bottomGradientColor)
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        updateCornerRadius()
    }

    @IBInspectable var fullRounded: Bool = false {
        didSet {
            updateCornerRadius()
        }
    }



    @IBInspectable var cornerRadiusOfButton : CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadiusOfButton
        }
    }

    func updateCornerRadius() {
        layer.cornerRadius = fullRounded ? (frame.size.height / 2) : cornerRadiusOfButton
    }


    @IBInspectable var borderWidth: CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }

    @IBInspectable var borderColor: UIColor? {
        set {
            guard let uiColor = newValue else { return }
            layer.borderColor = uiColor.cgColor
        }
        get {
            guard let color = layer.borderColor else { return nil }
            return UIColor(cgColor: color)
        }
    }

    private func setGradient(topGradientColor: UIColor?, bottomGradientColor: UIColor?) {
        if let topGradientColor = topGradientColor, let bottomGradientColor = bottomGradientColor {
            gradientLayer.frame = bounds
            gradientLayer.colors = [topGradientColor.cgColor, bottomGradientColor.cgColor]
            gradientLayer.borderColor = layer.borderColor
            gradientLayer.borderWidth = layer.borderWidth
            gradientLayer.cornerRadius = layer.cornerRadius
            layer.insertSublayer(gradientLayer, at: 0)
        } else {
            gradientLayer.removeFromSuperlayer()
        }
    }
}

but here is the result:

enter image description here

as you can see the width of the gradient layer button is incorret.

here is the constraint layout I use:

enter image description here

I want that gradient layer to have the same width as the original button, I suspect that the problem is in this line

gradientLayer.frame = bounds

but unfortunately I don't know how to set the gradient layer width to be the same size as the original button programmatically in @IBDesignable class

could you please help me to solve this issue ? thanks in advance


Solution

  • Override layoutSubviews inside GradientButton and update the gradientLayer frame as,

    override func layoutSubviews() {
        super.layoutSubviews()
    
        self.gradientLayer.frame = bounds
    }