iosswifttintcolor

How to keep image's tintColor for an UIButton?


I created a custom class CircularButton in which I can set a custom image, backgroundColor, tintColor for the image and inset to the edge of the button.

It's working fine, except for the tintColor. I want to be able to set the tintColor, but if I don't provide one, it should keep the original tintColor of my image (rendered as template image).

open class CircularButton: UIButton {

    public init(width: CGFloat, backgroundColor: UIColor? = nil, tintColor: UIColor? = nil, image: UIImage? = nil, contentMode: ContentMode? = nil, insets: UIEdgeInsets? = nil) {
        super.init(frame: .zero)

        self.backgroundColor = backgroundColor ?? .clear
        self.tintColor = tintColor ?? // issue is here
        self.imageEdgeInsets = insets ?? .zero
        self.imageView?.contentMode = contentMode ?? .scaleAspectFit

        setImage(image?.withRenderingMode(.alwaysTemplate), for: .normal)

        if width != 0 {
            widthAnchor.constraint(equalToConstant: width).isActive = true
        }

        heightAnchor.constraint(equalTo: widthAnchor).isActive = true
        clipsToBounds = true
    }

    override open func layoutSubviews() {
        super.layoutSubviews()

        layer.cornerRadius = frame.width / 2
    }

    public required init?(coder aDecoder: NSCoder) {
        fatalError()
    }
}

Here is how I initialize it :

let likeButton = CircularButton(width: 45, backgroundColor: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.5), tintColor: .white, image: UIImage(named: "heart"), insets: .init(top: 5, left: 5, bottom: 5, right: 5))

This is working, except that if I don't want to provide a tintColor, it takes the default blue tintColor for the button and render my image in blue.

Here is what I have tried in my custom class:

...

self.tintColor = tintColor ?? imageView?.tintColor

Solution

  • You are using .alwaysTemplate as RenderingMode wrongly here, this property is used to change the color of the image changing the original color for the tint Color in your component, you should use .alwaysOriginal if you want to keep the original color of the image in this component

    to fix this use .alwaysOriginal instead of .alwaysTemplate in this line

    setImage(image?.withRenderingMode(.alwaysTemplate), for: .normal)