UIImageView doesn't always tint template image

IosObjective CXcodeUiimageview

Ios Problem Overview


In the case below, there are two UIImageViews with the same settings and the same template image... But one tints the image, and one does not

I duplicated working UIImageView and placed it instead of the other and it worked. This happened to me multiple times and this solution always worked, but I still wonder what could I have done wrong? Can it be an Xcode bug? Did something similar happen to you? I have Xcode 8.1.

Xcode screenshot

Xcode screenshot

Ios Solutions


Solution 1 - Ios

Easy fix solution:

enter image description here

Just add a new runtime attribute which will set the tintColor of the UIImageView to the specified color and ensure the image is tinted.

You will still need to set your image to be rendered as a template image in your Images.xcassets file.

This way you dont need any additional outlets, extensions or lines of code.

Also take note: It will not apply the tintColor in the user defined attribute if the tintColor on the view is the same color, they must be different.

Solution 2 - Ios

Best solution I found that doesn't require a subclass or another IBInspectable attribute:

import UIKit

extension UIImageView {
    override open func awakeFromNib() {
        super.awakeFromNib()
        tintColorDidChange()
    }
}

Solution 3 - Ios

The problem stems from the value for tint having no null state (within the Storyboard/Interface Builder UI). In order for Xcode to decide whether a tint should be applied to a UIImageView there appears to be an additional test. In Xcode this is apparently done by evaluating the constraints applied to UIImageView. As far as I know this test is undocumented.

If you only have a "Spacing to nearest neighbor" constraint on two (or one) sides of your UIImageView then the tint is not applied regardless of the value set for UIImage.renderingMode.

If you have a "Spacing to nearest neighbor" constraint on three (or all) sides of your UIImageView then the tint is applied if the UIImage.renderingMode is set to .alwaysTemplate.

In a purely Storyboard/Interface Builder approach you set the UIImage.renderingMode of an image by adding it to an Asset Catalogue and then changing the "Render As" property of the Image Set to "Template Image".

Solution 4 - Ios

Try setting tintColor programmatically; it fixed the issue for me.

Solution 5 - Ios

I think there is a bug in UIImageView. If you set a tint color in the storyboard, it doesn't apply that tint even when the asset is set up to render as template.

The workaround is to apply the tint color to the UIImageView's parent view in the storyboard.

Or, set the tintColor to nil and then back again in code by binding the UIImageView to an outlet.

Solution 6 - Ios

use this extension to set UIImageView tintColor from interface builder.

extension UIImageView {
    @IBInspectable var imageColor: UIColor! {
        set {
            tintColor = newValue
        }
        get {
            tintColor
        }
    }
} 

Solution 7 - Ios

Runtime attribute trick did not work for me. I made this class just for fixing this kind of stuff. You'll just set to this class all the problematic image views.

final class TintedImageView: UIImageView {

    // WORKAROUND: Template images are not tinted when set using the Interface Builder.
    override func layoutSubviews() {
        super.layoutSubviews()
        let preferredTintColor = tintColor
        tintColor = nil
        tintColor = preferredTintColor
    }

}

Solution 8 - Ios

By removing my existing UIImageView and adding a new one my problem was gone. Apparently, the situation is that you should add the UIImageView AFTER adding the images to the Assets folder.

Solution 9 - Ios

Keep default tint colour in storyboard enter image description here

and add User defined runtime attribute with your chosen colour enter image description here

The storyboard will show the image with default tint but when you run, it will show your selected colour.

Solution 10 - Ios

Maybe it helps as I was banging my head for an hour until I realised something that I still quite don't understand.

I had my view in my .nib file and all the outlets except one (the UIImageView) had a non default tint colour. I tried all the suggested answer but the issue was solved by selecting a default tint colour for changing it after programatically.

enter image description here

enter image description here

Might it a bug?

Solution 11 - Ios

I had this issue with XCode 10.3. It's an XCode bug which seems to be related to adding an image to storyboard before adding it to assets.

What helped me is changing tint color to some random color then changing it back to default.

As a result XCode added <color key="tintColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> to storyboard XML which was missing before. Although it's added as colorSpace="custom" the XCode builder shows it as default.

Solution 12 - Ios

As @richardjsimkins mentioned, this does seem to at least in some cases have to do with constraints. In my case I wanted to add an image to the center of the launch screen, since in this case I am not able to set the tintColor programmatically. I had to find a pure Storyboard solution.

I found that the tintColor was not set when centering the image view with constraints, i.e. center horizontally/vertically in safe area, which corresponds to it having no "Spacing to nearest neighbor" constraints.

Instead I added a stack view with constraints to safe area leading/trailing/top/bottom and then embedded the image view in the safe area with alignment center, distribution fill. This resolves to the same positioning as directly centering the imageView in the safe area and this made the tintColor take effect.

I do not like having to resolve to using a stack view to force the tintColor to work, but I think it's a small and fairly clean workaround to the bug.

Solution 13 - Ios

iOS UIImageView and tint color and template image

  • tintColor has effect only on template image
  • template image will change all colors(except colors with alpha 0 - transparent color) to selected color and only Alpha will be taken into account.

It means that result image will be colorized into single color(tint color) with different alphas. That is why you can not colorize some specific parts of your image

Set image as template:

// Programmatic
let imageView = UIImageView()
imageView.image = imageView.image?.withRenderingMode(.alwaysTemplate)

// Xcode
<select image in assets> -> Attributes Inspector -> Render As -> Template Image

https://i.stack.imgur.com/nnoNE.png" height="100" />

Set tint color

imageView.tintColor = .red

> When you add a template image to a button or image view, you also specify a tint color. The view applies the tint color to every pixel that doesn't have an alpha of 0.0, causing the image's shape to adopt that color. To support different appearances, simply change the tint color. For example, you might apply a dark tint color in light environments and a light tint color in dark environments.

official doc - Create Tintable Images Using Template Images

Additional notes

  • When you set image as template(and don't set tintColor) - imageview will be colorized into default tint color
  • SVG staff
    • fill="#RRGGBBAA" doesn't work, you can use fill-opacity="0-1" instead

[Xcode and vector image]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZuzana PaulisView Question on Stackoverflow
Solution 1 - IosDavid ReesView Answer on Stackoverflow
Solution 2 - IosallaireView Answer on Stackoverflow
Solution 3 - IosrichardjsimkinsView Answer on Stackoverflow
Solution 4 - IosParamasivan SamuttiramView Answer on Stackoverflow
Solution 5 - IospaddlefishView Answer on Stackoverflow
Solution 6 - IosMinaView Answer on Stackoverflow
Solution 7 - IosMarlo QuidatoView Answer on Stackoverflow
Solution 8 - IosrudymatosView Answer on Stackoverflow
Solution 9 - IosKrutika SonawalaView Answer on Stackoverflow
Solution 10 - IosReimond HillView Answer on Stackoverflow
Solution 11 - IosGene SView Answer on Stackoverflow
Solution 12 - IosDarumarView Answer on Stackoverflow
Solution 13 - IosyoAlex5View Answer on Stackoverflow