Immagine a colori UIButton


294

Ho notato che quando inserisco un bianco o nero UIImagein un UISegmentedControlcolore automaticamente lo maschera in modo che corrisponda alla tinta del controllo segmentato. Ho pensato che fosse davvero bello, e mi chiedevo se avrei potuto farlo anche altrove. Ad esempio, ho un sacco di pulsanti che hanno una forma uniforme ma vari colori. Invece di creare un PNG per ogni pulsante, potrei in qualche modo usare questa maschera di colore per usare la stessa immagine per tutti loro, ma poi impostare un colore di tinta o qualcosa per cambiarne il colore reale?


Puoi pubblicare l'immagine che desideri utilizzare e anche l'immagine per il risultato desiderato?
Pratyusha Terli,

questo fare lo stesso dal costruttore di interfaccia stackoverflow.com/a/25179217/2051381
Chuy47

Risposte:


619

A partire da iOS 7, è disponibile un nuovo metodo UIImageper specificare la modalità di rendering. L'uso della modalità di rendering UIImageRenderingModeAlwaysTemplateconsente di controllare il colore dell'immagine dal colore della tinta del pulsante.

Objective-C

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

veloce

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red

14
Penso che sia meglio usare button.imageView.tintColor
M.Othman

3
@ M.Othman funziona solo per me quando uso button.tintColor e non button.imageview.tintColor
pnizzle

32
Ricorda solo di impostare la modalità di rendering dell'immagine sull'immagine in xcassets per @hashier
Decano

23
La creazione di un UIButton di tipo UIButtonTypeSystem rispetta automaticamente il tintColor impostato.
Carloshwa,

4
Se il tuo tintColorè troppo scuro, assicurati di adjustsImageWhenHighlightedNO. (O in IB: "Evidenziato regola l'immagine" è deselezionato.)
Jason Moore,

225

Come Ric ha già menzionato nel suo post , puoi impostare la modalità di rendering in codice, puoi anche farlo direttamente nel catalogo immagini, vedi l'immagine allegata di seguito. Basta impostare la Render AsaTemplate Image

inserisci qui la descrizione dell'immagine

Avvertenza ho avuto problemi con iOS 7 e questo approccio. Quindi, se usi anche iOS 7, potresti volerlo fare anche in codice, per essere sicuro, come descritto qui .


1
Come nota a margine, il file di immagine dovrebbe essere nero e trasparente (non in b & n)
Axel Guilmin,

6
@AxelGuilmin non proprio. L'immagine può essere di qualsiasi colore desiderato e trasparente. Qualsiasi colore diverso dal trasparente verrà convertito in uno generico e quindi verrà tinto con il colore nero per impostazione predefinita.
Alejandro Iván,

90

I pulsanti personalizzati vengono visualizzati nei rispettivi colori dell'immagine. Impostando il tipo di pulsante su "Sistema" nello storyboard (o su UIButtonTypeSystemnel codice), verrà visualizzata l'immagine del pulsante con il colore di tinta predefinito.

Tipo di pulsante Sistema Rendering Icone colorate

(testato su iOS9, Xcode 7.3)


2
Che può essere evitato con i metodi alwaysTemplate e tintColor suggeriti qui. Con il vantaggio del pulsante .system che si ottiene il cambiamento di colore con il tocco verso il basso sul rubinetto.
Chris Prince,

44

È necessario impostare la modalità di rendering dell'immagine su UIImageRenderingModeAlwaysTemplateper avere l' tintColoreffetto su UIImage. Ecco la soluzione in 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

28

Se hai un pulsante personalizzato con un'immagine di sfondo. Puoi impostare il colore della tinta del tuo pulsante e sovrascrivere l'immagine come segue.

Nelle risorse selezionare lo sfondo del pulsante che si desidera impostare il colore della tinta.

Nella finestra di ispezione degli attributi dell'immagine imposta il valore render su "Immagine modello"

inserisci qui la descrizione dell'immagine

Ora ogni volta che si imposta il button.tintColor = UIColor.redpulsante verrà visualizzato in rosso.


se sei qui puoi andare a questo link: useyourloaf.com/blog/styling-buttons-using-the-asset-catalog e andare alle immagini dei template (per fare da spiegazione)
cspam

Questa è una soluzione migliore in quanto riduce il codice e praticamente fa la stessa cosa della risposta accettata.
DS.

Penso che questo dovrebbe essere quello corretto. meno codice e facile da gestire.
Umair_UAS il

17

In Swift puoi farlo in questo modo:

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

Quindi dal tuo punto di vista DidLoad

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

E per modificare il colore

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

EDIT Xcode 8 ora è possibile anche solo la modalità di rendering delle immagini nei tuoi .xcassets a Template immagine e quindi non c'è bisogno di specificamente dichiararla in var exampleImagepiù


14

Non sai esattamente cosa vuoi, ma questo metodo di categoria maschererà un UIImage con un colore specificato in modo da poter avere una singola immagine e cambiarne il colore con quello che vuoi.

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;    
}

Importa la categoria ImageUtils e fai qualcosa del genere ...

#import "ImageUtils.h"

...

UIImage *icon = [UIImage imageNamed:ICON_IMAGE];

UIImage *redIcon = [icon maskWithColor:UIColor.redColor];
UIImage *blueIcon = [icon maskWithColor:UIColor.blueColor];

3
Usa kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLastsuCGBitmapContextCreate
Luis Ascorbe il

4
Bello, ma deve essere ottimizzato per la grafica Retina ... Quando eseguo questo su un'immagine Retina, mi restituisce una non retina.
Jowie,

Per supportare i dispositivi Retina è possibile utilizzare la proprietà scale della UIDeviceclasse: CGFloat scale = [UIScreen mainScreen].scale; CGFloat width = self.size.width * scale; CGFloat height = self.size.height * scale;la scaleproprietà esiste a partire da iOS 4.0.
Philipp Frischmuth,

È inoltre necessario utilizzare il scalevalore quando UIImageviene creato:UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:scale orientation:self.imageOrientation];
Philipp Frischmuth

8

Swift 4 con customType:

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

5

Per 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);

5

Swift 3 :

Questa soluzione potrebbe essere comoda se hai già impostato l'immagine tramite il builder dell'interfaccia xCode. Fondamentalmente hai un'estensione per colorare un'immagine:

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
    }
}

Quindi, puoi preparare questa estensione UIButton per colorare l'immagine per un determinato stato:

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)
        }
    }
}

Uso:

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

PS (funziona bene anche nelle celle della tabella, non è necessario chiamare il setNeedDisplay()metodo, il cambio di colore è immediato a causa dell'estensione UIImage ..


3

Se vuoi mascherare manualmente la tua immagine, ecco il codice aggiornato che funziona con le schermate della retina

- (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;
}

2

Dovresti provare

Dopo aver impostato la cornice

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];

}

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)

1

Cambia colore pulsante o visualizzazione immagine tinta colore Swift:

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

btn.imageView?.tintColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)

-1

Nessuna delle precedenti ha funzionato per me, perché la tinta è stata cancellata dopo il clic. Ho dovuto usare

button.setImageTintColor(Palette.darkGray(), for: UIControlState())
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.