Image couleur UIButton

294

J'ai remarqué que lorsque je place un blanc ou un noir UIImagedans un UISegmentedControlmasque de couleur automatique, il correspond à la teinte du contrôle segmenté. Je pensais que c'était vraiment cool et je me demandais si je pouvais le faire ailleurs aussi. Par exemple, j'ai un tas de boutons qui ont une forme uniforme mais des couleurs variées. Au lieu de créer un PNG pour chaque bouton, pourrais-je utiliser ce masquage de couleur pour utiliser la même image pour chacun d'eux, puis définir une couleur de teinte ou quelque chose pour changer leur couleur réelle?

Logan Shire
la source
Pouvez-vous publier l'image que vous souhaitez utiliser et également l'image pour le résultat souhaité?
Pratyusha Terli
cela fait la même chose du générateur d'interface stackoverflow.com/a/25179217/2051381
Chuy47

Réponses:

619

Depuis iOS 7, il existe une nouvelle méthode UIImagepour spécifier le mode de rendu. L'utilisation du mode de rendu UIImageRenderingModeAlwaysTemplatepermettra à la couleur de l'image d'être contrôlée par la couleur de teinte du bouton.

Objectif c

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [[UIImage imageNamed:@"image_name"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[button setImage:image forState:UIControlStateNormal]; 
button.tintColor = [UIColor redColor];

Rapide

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red
Ric Santos
la source
14
Je pense qu'il vaut mieux utiliser button.imageView.tintColor
M.Othman
3
@ M.Othman ne fonctionne pour moi que lorsque j'utilise button.tintColor et non button.imageview.tintColor
pnizzle
32
N'oubliez pas de définir le mode de rendu d'image sur l'image dans xcassets par @hashier
Dean
23
La création d'un UIButton de type UIButtonTypeSystem honorera automatiquement la teinte que vous définissez.
carloshwa
4
Si votre tintColorest trop sombre, assurez-vous que adjustsImageWhenHighlightedNON. (Ou dans IB: "Highlighted Adjusts Image" n'est pas coché.)
Jason Moore
225

Comme Ric l'a déjà mentionné dans son article, vous pouvez définir le mode de rendu en code, vous pouvez également le faire directement dans le catalogue d'images, voir l'image ci-jointe. Réglez simplement le Render AssurTemplate Image

entrez la description de l'image ici

Attention, j'ai eu des problèmes avec iOS 7 et cette approche. Donc, si vous utilisez iOS 7 également, vous pouvez également le faire en code, comme décrit ici .

hashier
la source
1
En remarque, le fichier image doit être noir et transparent (pas en noir et blanc)
Axel Guilmin
6
@AxelGuilmin pas vraiment. Votre image peut être de n'importe quelle couleur et transparente. Toute couleur différente de transparente sera convertie en une couleur générique , puis elle sera teintée de couleur noire par défaut.
Alejandro Iván
90

Les boutons personnalisés apparaissent dans leurs couleurs d'image respectives. La définition du type de bouton sur "Système" dans le storyboard (ou UIButtonTypeSystemdans le code) rendra l'image du bouton avec la couleur de teinte par défaut.

Type de bouton Icônes de rendu du système teintées

(testé sur iOS9, Xcode 7.3)

auco
la source
2
Ce qui peut être évité avec les méthodes alwaysTemplate et tintColor suggérées ici. Avec l'avantage du bouton .system, vous obtenez le changement de couleur en touchant le robinet.
Chris Prince
44

Vous devez définir le mode de rendu d'image UIImageRenderingModeAlwaysTemplatesur pour avoir l' tintColoreffet sur l'image UII. Voici la solution dans Swift:

let image = UIImage(named: "image-name")
let button = UIButton()
button.setImage(image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: .Normal)
button.tintColor = UIColor.whiteColor()

SWIFT 4x

button.setImage(image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate), for: .normal)
button.tintColor = UIColor.blue
Nick Wargnier
la source
28

Si vous avez un bouton personnalisé avec une image d'arrière-plan, vous pouvez définir la couleur de teinte de votre bouton et remplacer l'image par ce qui suit.

Dans les ressources, sélectionnez l'arrière-plan du bouton que vous souhaitez définir la couleur de teinte.

Dans l'inspecteur d'attributs de l'image, réglez la valeur sur "Template Image"

entrez la description de l'image ici

Maintenant, chaque fois que vous définissez button.tintColor = UIColor.redvotre bouton sera affiché en rouge.

Ilker Baltaci
la source
si vous êtes ici, vous pouvez aller sur ce lien: useyourloaf.com/blog/styling-buttons-using-the-asset-catalog et descendre vers les images modèles (pour servir d'explication)
cspam
C'est une meilleure solution car elle réduit le code et fait à peu près la même chose que la réponse acceptée.
DS.
Je pense que cela devrait être le bon. moins de code et facile à manipuler.
Umair_UAS
17

Dans Swift, vous pouvez le faire comme ceci:

var exampleImage = UIImage(named: "ExampleImage.png")?.imageWithRenderingMode(.AlwaysTemplate)

Puis dans votre viewDidLoad

exampleButtonOutlet.setImage(exampleImage, forState: UIControlState.Normal)

Et pour modifier la couleur

exampleButtonOutlet.tintColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1) //your color

EDIT Xcode 8 Maintenant , vous pouvez aussi tout simplement le mode de rendu de l'image dans votre .xcassets à l' image modèle et vous n'avez pas besoin de déclarer spécifiquement dans le var exampleImageplus

henrik-dmg
la source
14

Je ne sais pas exactement ce que vous voulez, mais cette méthode de catégorie masquera un UIImage avec une couleur spécifiée afin que vous puissiez avoir une seule image et changer sa couleur en ce que vous voulez.

ImageUtils.h

- (UIImage *) maskWithColor:(UIColor *)color;

ImageUtils.m

-(UIImage *) maskWithColor:(UIColor *)color 
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width;
    CGFloat height = self.size.height;
    CGRect bounds = CGRectMake(0,0,width,height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);    
    CGContextFillRect(bitmapContext, bounds);

    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage];

    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);

    return coloredImage;    
}

Importez la catégorie ImageUtils et faites quelque chose comme ça ...

#import "ImageUtils.h"

...

UIImage *icon = [UIImage imageNamed:ICON_IMAGE];

UIImage *redIcon = [icon maskWithColor:UIColor.redColor];
UIImage *blueIcon = [icon maskWithColor:UIColor.blueColor];
Kirby Todd
la source
3
Utiliser kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLastsurCGBitmapContextCreate
Luis Ascorbe
4
Bien, mais doit être peaufiné pour les graphiques Retina ... Lorsque je lance ceci sur une image Retina, cela me renvoie une image non-rétine.
jowie
Pour prendre en charge les appareils Retina, vous pouvez utiliser la propriété scale de la UIDeviceclasse: CGFloat scale = [UIScreen mainScreen].scale; CGFloat width = self.size.width * scale; CGFloat height = self.size.height * scale;La scalepropriété existe depuis iOS 4.0.
Philipp Frischmuth
Vous devez également utiliser la scalevaleur lors de la UIImagecréation de:UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:scale orientation:self.imageOrientation];
Philipp Frischmuth
8

Swift 4 avec customType:

let button = UIButton(frame: aRectHere)
    let buttonImage = UIImage(named: "imageName")
    button.setImage(buttonImage?.withRenderingMode(.alwaysTemplate), for: .normal)
    button.tintColor = .white
aBikis
la source
5

Pour Xamarin.iOS (C #):

        UIButton messagesButton = new UIButton(UIButtonType.Custom);
        UIImage icon = UIImage.FromBundle("Images/icon.png");
        messagesButton.SetImage(icon.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), UIControlState.Normal);
        messagesButton.TintColor = UIColor.White;
        messagesButton.Frame = new RectangleF(0, 0, 25, 25);
Maciej
la source
5

Swift 3 :

Cette solution pourrait être confortable si vous avez déjà défini votre image via le générateur d'interface xCode. Fondamentalement, vous avez une extension pour coloriser une image:

extension UIImage {
    public func image(withTintColor color: UIColor) -> UIImage{
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        let context: CGContext = UIGraphicsGetCurrentContext()!
        context.translateBy(x: 0, y: self.size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        context.setBlendMode(CGBlendMode.normal)
        let rect: CGRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
        context.clip(to: rect, mask: self.cgImage!)
        color.setFill()
        context.fill(rect)
        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }
}

Ensuite, vous pouvez préparer cette extension UIButton pour coloriser l'image pour un état particulier:

extension UIButton {
    func imageWith(color:UIColor, for: UIControlState) {
        if let imageForState = self.image(for: state) {
            self.image(for: .normal)?.withRenderingMode(.alwaysTemplate)
            let colorizedImage = imageForState.image(withTintColor: color)
            self.setImage(colorizedImage, for: state)
        }
    }
}

Usage:

myButton.imageWith(.red, for: .normal)

PS (fonctionne bien également dans les cellules du tableau, vous n'avez pas besoin d'appeler la setNeedDisplay()méthode, le changement de couleur est immédiat en raison de l' extension UIImage .

Alessandro Ornano
la source
3

Si vous souhaitez masquer manuellement votre image, voici un code mis à jour qui fonctionne avec les écrans rétine

- (UIImage *)maskWithColor:(UIColor *)color
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width * self.scale;
    CGFloat height = self.size.height * self.scale;
    CGRect bounds = CGRectMake(0,0,width,height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);
    CGContextFillRect(bitmapContext, bounds);

    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:self.scale orientation:self.imageOrientation];

    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);

    return coloredImage;
}
Josh Bernfeld
la source
2

Tu devrais essayer

Après avoir réglé le cadre

NSArray *arr10 =[NSArray arrayWithObjects:btn1,btn2,nil];
for(UIButton *btn10 in arr10)
{
CAGradientLayer *btnGradient2 = [CAGradientLayer layer];
btnGradient2.frame = btn10.bounds;

btnGradient2.colors = [NSArray arrayWithObjects:
                       (id)[[UIColor colorWithRed:151.0/255.0f green:206.0/255.5 blue:99.0/255.0 alpha:1] CGColor],
                       (id)[[UIColor colorWithRed:126.0/255.0f green:192.0/255.5 blue:65.0/255.0 alpha:1]CGColor],
                       nil];
[btn10.layer insertSublayer:btnGradient2 atIndex:0];

}
guptha
la source
2

Swift 3.0

    let image = UIImage(named:"NoConnection")!

 warningButton = UIButton(type: .system)        
    warningButton.setImage(image, for: .normal)
    warningButton.tintColor = UIColor.lightText
    warningButton.frame = CGRect(origin: CGPoint(x:-100,y:0), size: CGSize(width: 59, height: 56))

    self.addSubview(warningButton)
Jad
la source
1

Changer l'image du bouton ou la couleur de la teinte de la vue d'image Swift:

btn.imageView?.image = btn.imageView?.image?.withRenderingMode(.alwaysTemplate)

btn.imageView?.tintColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
Urvish Modi
la source
-1

Rien de ce qui précède n'a fonctionné pour moi, car la teinte a été effacée après le clic. Je devais utiliser

button.setImageTintColor(Palette.darkGray(), for: UIControlState())
Szymon Klimaszewski
la source