467 votes

Comment modifier la couleur de l'image (tintColor) dans iOS et WatchKit ?

J'ai un UIImageView appelé "theImageView", avec une UIImage d'une seule couleur (fond transparent) comme le cœur noir de gauche ci-dessous. Comment puis-je changer la couleur de cette image par programme dans iOS 7 ou supérieur, comme la méthode de teinte utilisée dans les icônes de la barre de navigation d'iOS 7+ ?

Cette méthode peut-elle également fonctionner dans WatchKit pour une application Apple Watch ?

enter image description here

4 votes

Que voulez-vous dire par "le code suivant est erroné", la mise en place d'une UIImage avec UIImageRenderingModeAlwaysTemplate et ensuite UIImageVIew 's tintColor Fonctionne. (dans mon code ^^)

2 votes

Utilisez un png avec transparence comme celui-ci

4 votes

Vous devriez vraiment déplacer votre réponse dans la section des réponses, car je pense que c'est la meilleure et la plus moderne.

913voto

Duncan Babbage Points 3732

iOS
Pour une application iOS, en Swift 3, 4 ou 5 :

theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate)
theImageView.tintColor = UIColor.red

Pour Swift 2 :

theImageView.image = theImageView.image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
theImageView.tintColor = UIColor.redColor()

En attendant, la solution moderne en Objective-C est :

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];

Watchkit
Dans WatchKit pour les apps Apple Watch, vous pouvez définir l' couleur de teinte pour une image modèle .

  1. Vous devez ajouter votre image à un catalogue d'actifs dans votre application WatchKit, et définir le jeu d'images à rendre en tant qu'image modèle dans l'inspecteur des attributs. Contrairement à une application iPhone, vous ne pouvez pas, pour l'instant, définir le rendu du modèle dans le code de l'extension WatchKit.
  2. Définissez cette image pour qu'elle soit utilisée dans votre WKInterfaceImage dans le constructeur d'interface de votre application.
  3. Créez un IBOutlet dans votre WKInterfaceController pour le WKInterfaceImage appelé 'theImage'...

Pour ensuite régler la couleur de la teinte dans Swift 3 ou 4 :

theImage.setTintColor(UIColor.red)

Swift 2 :

theImage.setTintColor(UIColor.redColor())

Pour ensuite définir la couleur de la teinte en Objective-C :

[self.theImage setTintColor:[UIColor redColor]];

Si vous utilisez une image modèle et n'appliquez pas de couleur de teinte, la teinte globale de votre application WatchKit sera appliquée. Si vous n'avez pas défini de teinte globale, theImage sera teintée en bleu clair par défaut lorsqu'elle sera utilisée comme image modèle.

2 votes

C'est la meilleure et la plus simple des solutions.

6 votes

ImageWithRenderingMode est trop lent. Dans le storyboard et l'image Assets. vous pouvez également modifier ce deux : Mettre à jour le Render Mode en Template Image - c'est une meilleure solution.

0 votes

Parfait, maintenant j'utilise cette méthode basée sur votre code : + (UIImageView ) tintImageView : (UIImageView *)imageView withColor : (UIColor ) color{ imageView.image = [imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] ; [imageView setTintColor:color] ; return imageView ; }

128voto

JerryZhou Points 856

Dans le storyboard et l'image Assets, vous pouvez également modifier ces deux éléments :

Mettre à jour le mode de rendu en image modèle

Update the Render Mode to Template Image in Image Assets

Mettez à jour la couleur de la teinte dans les vues.

Update the tint Color in Views in Views

125voto

iamamused Points 902

Voici une catégorie qui devrait faire l'affaire

@interface UIImage(Overlay)
@end

@implementation UIImage(Overlay)

- (UIImage *)imageWithColor:(UIColor *)color1
{
        UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(context, 0, self.size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, kCGBlendModeNormal);
        CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
        CGContextClipToMask(context, rect, self.CGImage);
        [color1 setFill];
        CGContextFillRect(context, rect);
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return newImage;
}
@end

donc vous le feriez :

theImageView.image = [theImageView.image imageWithColor:[UIColor redColor]];

0 votes

Merci pour cette réponse très valable, je suppose que mon code était correct dès le départ, je devrais répondre à ma propre question et vous donner un +1 indépendamment

125voto

gotnull Points 4918

J'ai dû faire cela en Swift en utilisant un fichier extension .

J'ai pensé que je pourrais partager comment j'ai fait :

extension UIImage {
    func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext() as CGContextRef
        CGContextTranslateCTM(context, 0, self.size.height)
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, CGBlendMode.Normal)

        let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect
        CGContextClipToMask(context, rect, self.CGImage)
        CGContextFillRect(context, rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext() as UIImage
        UIGraphicsEndImageContext()

        return newImage
    }
}

Utilisation :

theImageView.image = theImageView.image.imageWithColor(UIColor.redColor())

Swift 4

extension UIImage {
    func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext()
        context?.translateBy(x: 0, y: self.size.height)
        context?.scaleBy(x: 1.0, y: -1.0)
        context?.setBlendMode(CGBlendMode.normal)

        let rect = CGRect(origin: .zero, size: CGSize(width: self.size.width, height: self.size.height))
        context?.clip(to: rect, mask: self.cgImage!)
        context?.fill(rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }
}

Utilisation :

theImageView.image = theImageView.image?.imageWithColor(color1: UIColor.red)

1 votes

Pour votre information, cela n'a pas fonctionné pour moi jusqu'à ce que je déplace le fichier color1.setFill() juste en dessous de la première ligne de la méthode UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) .

0 votes

@Aaron Mise à jour basée sur votre commentaire. Merci.

0 votes

Use of unresolved identifier "kCGBlendModeNormal" - Erreur dans Xcode 7.0 beta 2

47voto

Puttin Points 1236

Si quelqu'un a une solution sans UIImageView :

// (Swift 3)
extension UIImage {
    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
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X