Utilisation de la couleur Tint sur UIImageView

118

J'ai ma propre sous-classe de UIButton. J'ajoute UIImageViewdessus et ajoute une image. Je voudrais le peindre sur l'image avec une couleur de teinte mais cela ne fonctionne pas.

Jusqu'à présent, j'ai:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        self.backgroundColor = [UIColor clearColor];
        self.clipsToBounds = YES;

        self.circleView = [[UIView alloc]init];
        self.circleView.backgroundColor = [UIColor whiteColor];
        self.circleView.layer.borderColor = [[Color getGraySeparatorColor]CGColor];
        self.circleView.layer.borderWidth = 1;
        self.circleView.userInteractionEnabled = NO;
        self.circleView.translatesAutoresizingMaskIntoConstraints = NO;
        [self addSubview:self.circleView];

        self.iconView = [[UIImageView alloc]init];
        [self.iconView setContentMode:UIViewContentModeScaleAspectFit];
        UIImage * image = [UIImage imageNamed:@"more"];
        [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        self.iconView.image = image;
        self.iconView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.circleView addSubview:self.iconView];
        ...

et sur sélection:

- (void) setSelected:(BOOL)selected
{
    if (selected) {
        [self.iconView setTintColor:[UIColor redColor]];
        [self.circleView setTintColor:[UIColor redColor]];
    }
    else{
        [self.iconView setTintColor:[UIColor blueColor]];
        [self.circleView setTintColor:[UIColor blueColor]];
    }  
}

Qu'ai-je fait de mal? (La couleur de l'image reste toujours la même qu'à l'origine.)

Marko Zadravec
la source
pouvez-vous le faire setTintColorlorsque vous créez le iconView ?
Himanshu Joshi
1
voulez-vous dire après self.iconView = [UIImageView alloc] ...? Oui je peux, mais ça ne marche pas.
Marko Zadravec
Utilisez CGContext alors. Peut-être pouvez-vous trouver votre réponse ici stackoverflow.com/a/19275079/1790571
Himanshu Joshi
Oui, je vois ce message mais je ne comprends vraiment pas pourquoi mon code ne fonctionne pas. L'utilisation de la couleur de teinte est un chemin beaucoup plus propre.
Marko Zadravec

Réponses:

237

Au lieu de ce code:

[image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

tu aurais dû:

image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Utilisez ceci dans Swift 4.1

image = UIImage(named: "name")!.withRenderingMode(.alwaysTemplate)
Marko Zadravec
la source
9
Pas une erreur stupide, mais un détail très important. Merci d'avoir publié ceci. Vous venez de me faire gagner beaucoup de temps. (faute de frappe corrigée)
Alex Zavatone
47
Vous pouvez sélectionner l'image dans les actifs et sélectionner dans le mode de rendu par défaut du panneau de droite
Nikolay Shubenkov
Excellent! Mais comment revenir à l'image originale non teintée?
Marsman
Si vous souhaitez obtenir une image non teintée, vous pouvez: stocker une image teintée dans une variable différente: UIImage image2 = [image imageWithR ....], ou vous pouvez à nouveau charger l'image à partir du fichier: image = [UIImage imageNamed: @ "more" ];
Marko Zadravec
89

Vous pouvez également simplement définir cela sur votre élément. Assurez-vous que votre image contient tous les pixels blancs + transparent. entrez la description de l'image ici

StackUnderflow
la source
6
J'ai fait tout cela, mais pour une raison quelconque, le tintColor ne fonctionne pas pour moi. Une idée de ce que je pourrais essayer d'autre?
Banana
1
Quel type de format d'image utilisez-vous? Et l'image est-elle entièrement blanche + alpha?
StackUnderflow
3
Bizarrement, lors de mes premiers essais, seules 2/3 des images ont pris la couleur de la teinte. Après le nettoyage et la construction, toutes les images ont pris la teinte.
MathewS
Peut-être pourriez-vous le signaler à Apple?
StackUnderflow
11
@Banana, il s'agit d'un problème connu des images n'utilisant pas la couleur de teinte. Je l'avais signalé à Apple il y a quelque temps et ils l'ont marqué comme un double afin qu'ils le sachent définitivement. La solution de contournement consiste à ne pas définir votre UIImageView sur une image sur le Storyboard. Il suffit donc d'avoir un UIImageView vierge, puis de le définir dans viewDidLoad (ou ailleurs) et vous verrez alors le tintColor sur l'image.
Mark Moeykens
38

(Impossible de modifier le message @Zhaolong Zhong)

Dans Swift 3.0 , vous pouvez faire:

let image = UIImage(named: "your_image_name")!.withRenderingMode(.alwaysTemplate)

yourImageView.image = image

yourImageView.tintColor = UIColor.blue
odemolliens
la source
19

Dans swift 2.0+, vous pouvez faire:

let image = UIImage(named: "your_image_name")!.imageWithRenderingMode(.AlwaysTemplate)

yourImageView.image = image

yourImageView.tintColor = UIColor.blueColor()
Zhaolong Zhong
la source
11

Version Swift: 5.2

let tintableImage = UIImage(named: "myImage")?.withRenderingMode(.alwaysTemplate)
imageView.image = tintableImage
imageView.tintColor = UIColor.red

Objectif c

self.imgView.image = [self.imgView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[self.imgView setTintColor:[UIColor darkGrayColor]];

Ou

Vous pouvez également simplement définir cela sur votre élément.

entrez la description de l'image ici

Nischal Hada
la source
7

Un pas en avant. Ceci est une sous-classe de UIImageView. (Solution non exacte pour la question d'origine.) À utiliser dans Interface Builder en définissant le nom de classe sur TintedImageView. Mises à jour en temps réel à l'intérieur du concepteur à mesure que la couleur de la teinte change.

(Swift 3.1, Xcode 8.3)

import UIKit

@IBDesignable class TintedImageView: UIImageView {
    override func prepareForInterfaceBuilder() {
        self.configure()
    }

    override func awakeFromNib() {
        super.awakeFromNib()

        self.configure()
    }

    @IBInspectable override var tintColor: UIColor! {
        didSet {
            self.configure()
        }
    }

    private func configure() {
        self.image = self.image?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
    }
}
Daniel
la source
2
ne fonctionne pas, mais il modifie func configure en: self.image = self.image? .withRenderingMode (UIImageRenderingMode.alwaysTemplate) let color = super.tintColor super.tintColor = UIColor.clear super.tintColor = color
lolo_house
5

Rendre l'imageView

    let imageView = UIImageView(frame: frame!)
    imageView.contentMode = .ScaleAspectFit
    imageView.tintColor = tintColor

Faire l'image

    let mainBundle = NSBundle.mainBundle()
    var image = UIImage(named: filename!, inBundle: mainBundle, compatibleWithTraitCollection: nil)
    image = image?.imageWithRenderingMode(.AlwaysTemplate)

Câblez-les ensemble

    imageView?.image = image

Affichez-le

view.addSubview(imageView)
Gary Davies
la source
1

tout dit est correct. ma contribution Si vous ne pouvez pas / ne voulez pas appliquer à chaque UiImageView, OU pour plus d'efficacité, vous devez effectuer un rendu UNE FOIS (ou exemple pour les cellules de tables vues)

func tint(with color: UIColor) -> UIImage {
        var image = withRenderingMode(.alwaysTemplate)
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        color.set()

        image.draw(in: CGRect(origin: .zero, size: size))
        image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }

Et définissez tous les éléments de l'interface utilisateur cette UIImage.

ingconti
la source
1

La réponse @odemolliens devrait juste fonctionner.

Mais si vous rencontrez toujours des problèmes, assurez-vous que la couleur de teinte que vous appliquez à UIImageView est différente de celle définie dans Interface Builder.

rockdaswift
la source