Cambia il colore di png nei pulsanti - ios


93

Ho un set di icone che ho creato che sono PNG bianchi trasparenti:

inserisci qui la descrizione dell'immagine

E quello che vorrei fare è essere in grado di tingerli in altri colori. Come blu, grigio, ecc.

Ho notato che "cliccati / toccati" cambiano automaticamente in un grigio. Quindi presumo di poter cambiare quel grigio in quello che mi piace con un tocco o il suo stato normale:

inserisci qui la descrizione dell'immagine

Quale sarebbe il modo migliore per raggiungere questo obiettivo?

Risposte:


225

Il codice seguente imposterà il colore della tinta per lo stato normale del pulsante:

Per Swift 4 e versioni successive:

let origImage = UIImage(named: "imageName")
let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
btn.setImage(tintedImage, for: .normal)
btn.tintColor = .red

È possibile modificare il colore della tinta in base alle proprie necessità quando lo stato cambia per il pulsante.


Versioni precedenti

Per Swift 3:

let origImage = UIImage(named: "imageName")
let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
btn.setImage(tintedImage, forState: .normal)
btn.tintColor = .redColor

Per Swift 2: vedere la cronologia delle revisioni.


Meraviglioso Ma come si torna all'immagine originale (non colorata)?
Marsman

@Marsman se guardi la mia soluzione originaImage rappresenta l'immagine originale e tintedImage rappresenta la versione colorata dell'immagine originale, quindi non stai sostituendo l'immagine originale ma ne crei una nuova versione e avrai due versioni della stessa immagine che puoi usare come secondo le tue necessità
Yuvrajsinh

non funziona in iOS 11 con xcode 9.1. Quando Aggiungi il colore della tinta, cambia completamente il colore di imageView.
Vineesh TP

Le varie modifiche hanno introdotto inesattezze in questa risposta.
Eric Aya

13

iOS 7 ha introdotto una proprietà chiamata tintColor per le visualizzazioni (incluso UIImageView). Tuttavia, è anche necessario impostare il tipo di rendering sull'UIImage affinché abbia effetto.

UIImage *originalImage = [UIImage imageNamed:@"image.png"];
UIImage *tintedImage = [originalImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImageView *imageView = [[UIImageView alloc] initWithImage:tintedImage];

imageView.tintColor = [UIColor grayColor];
[self.view addSubview:imageView];

Questo dovrebbe produrre l'effetto che stai cercando in uno stato predefinito.


10

Puoi usare questa estensione:

import UIKit

extension CGContext {

    func fill(_ rect: CGRect,
              with mask: CGImage,
              using color: CGColor) {

        saveGState()
        defer { restoreGState() }

        translateBy(x: 0.0, y: rect.size.height)
        scaleBy(x: 1.0, y: -1.0)
        setBlendMode(.normal)

        clip(to: rect, mask: mask)

        setFillColor(color)
        fill(rect)
    }
}

extension UIImage {

    func filled(with color: UIColor) -> UIImage {
        let rect = CGRect(origin: .zero, size: self.size)
        guard let mask = self.cgImage else { return self }

        if #available(iOS 10.0, *) {
            let rendererFormat = UIGraphicsImageRendererFormat()
            rendererFormat.scale = self.scale

            let renderer = UIGraphicsImageRenderer(size: rect.size,
                                                   format: rendererFormat)
            return renderer.image { context in
                context.cgContext.fill(rect,
                                       with: mask,
                                       using: color.cgColor)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(rect.size,
                                                   false,
                                                   self.scale)
            defer { UIGraphicsEndImageContext() }

            guard let context = UIGraphicsGetCurrentContext() else { return self }

            context.fill(rect,
                         with: mask,
                         using: color.cgColor)
            return UIGraphicsGetImageFromCurrentImageContext() ?? self
        }
    }
}

1
Anche questo non funziona per me. Quando utilizzo questo metodo, tutto ciò che vedo è il colore, non l'immagine che ha tinto quel colore.
Moebius

9

Per cambiare la tonalità dell'immagine ( scelta , immagine classica , foto ) usa quello:

Immagine di esempio: inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Swift 2

public extension UIImage {
    /**
     Tint, Colorize image with given tint color<br><br>
     This is similar to Photoshop's "Color" layer blend mode<br><br>
     This is perfect for non-greyscale source images, and images that have both highlights and shadows that should be preserved<br><br>
     white will stay white and black will stay black as the lightness of the image is preserved<br><br>

     <img src="http://yannickstephan.com/easyhelper/tint1.png" height="70" width="120"/>

     **To**

     <img src="http://yannickstephan.com/easyhelper/tint2.png" height="70" width="120"/>

     - parameter tintColor: UIColor

     - returns: UIImage
     */
    public func tintPhoto(tintColor: UIColor) -> UIImage {

        return modifiedImage { context, rect in
            // draw black background - workaround to preserve color of partially transparent pixels
            CGContextSetBlendMode(context, .Normal)
            UIColor.blackColor().setFill()
            CGContextFillRect(context, rect)

            // draw original image
            CGContextSetBlendMode(context, .Normal)
            CGContextDrawImage(context, rect, self.CGImage)

            // tint image (loosing alpha) - the luminosity of the original image is preserved
            CGContextSetBlendMode(context, .Color)
            tintColor.setFill()
            CGContextFillRect(context, rect)

            // mask by alpha values of original image
            CGContextSetBlendMode(context, .DestinationIn)
            CGContextDrawImage(context, rect, self.CGImage)
        }
    }
    /**
     Tint Picto to color

     - parameter fillColor: UIColor

     - returns: UIImage
     */
    public func tintPicto(fillColor: UIColor) -> UIImage {

        return modifiedImage { context, rect in
            // draw tint color
            CGContextSetBlendMode(context, .Normal)
            fillColor.setFill()
            CGContextFillRect(context, rect)

            // mask by alpha values of original image
            CGContextSetBlendMode(context, .DestinationIn)
            CGContextDrawImage(context, rect, self.CGImage)
        }
    }
    /**
     Modified Image Context, apply modification on image

     - parameter draw: (CGContext, CGRect) -> ())

     - returns: UIImage
     */
    private func modifiedImage(@noescape draw: (CGContext, CGRect) -> ()) -> UIImage {

        // using scale correctly preserves retina images
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        let context: CGContext! = UIGraphicsGetCurrentContext()
        assert(context != nil)

        // correctly rotate image
        CGContextTranslateCTM(context, 0, size.height);
        CGContextScaleCTM(context, 1.0, -1.0);

        let rect = CGRectMake(0.0, 0.0, size.width, size.height)

        draw(context, rect)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

UPD

Swift 3

extension UIImage {

    /**
     Tint, Colorize image with given tint color<br><br>
     This is similar to Photoshop's "Color" layer blend mode<br><br>
     This is perfect for non-greyscale source images, and images that have both highlights and shadows that should be preserved<br><br>
     white will stay white and black will stay black as the lightness of the image is preserved<br><br>

     <img src="http://yannickstephan.com/easyhelper/tint1.png" height="70" width="120"/>

     **To**

     <img src="http://yannickstephan.com/easyhelper/tint2.png" height="70" width="120"/>

     - parameter tintColor: UIColor

     - returns: UIImage
     */
    func tintPhoto(_ tintColor: UIColor) -> UIImage {

        return modifiedImage { context, rect in
            // draw black background - workaround to preserve color of partially transparent pixels
            context.setBlendMode(.normal)
            UIColor.black.setFill()
            context.fill(rect)

            // draw original image
            context.setBlendMode(.normal)
            context.draw(cgImage!, in: rect)

            // tint image (loosing alpha) - the luminosity of the original image is preserved
            context.setBlendMode(.color)
            tintColor.setFill()
            context.fill(rect)

            // mask by alpha values of original image
            context.setBlendMode(.destinationIn)
            context.draw(context.makeImage()!, in: rect)
        }
    }

    /**
     Tint Picto to color

     - parameter fillColor: UIColor

     - returns: UIImage
     */
    func tintPicto(_ fillColor: UIColor) -> UIImage {

        return modifiedImage { context, rect in
            // draw tint color
            context.setBlendMode(.normal)
            fillColor.setFill()
            context.fill(rect)

            // mask by alpha values of original image
            context.setBlendMode(.destinationIn)
            context.draw(cgImage!, in: rect)
        }
    }

    /**
     Modified Image Context, apply modification on image

     - parameter draw: (CGContext, CGRect) -> ())

     - returns: UIImage
     */
    fileprivate func modifiedImage(_ draw: (CGContext, CGRect) -> ()) -> UIImage {

        // using scale correctly preserves retina images
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        let context: CGContext! = UIGraphicsGetCurrentContext()
        assert(context != nil)

        // correctly rotate image
        context.translateBy(x: 0, y: size.height)
        context.scaleBy(x: 1.0, y: -1.0)

        let rect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)

        draw(context, rect)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }

}

puoi dirmi come usare questi metodi significa come chiamarli?
ashmi123

Questo non funziona affatto per me. Ho un PNG impostato come immagine del pulsante. Quando uso tintPhoto o tintPicto, semplicemente non funzionano.
Moebius

hai aggiunto la tua immagine conRenderingMode (.alwaysTemplate)? @Moebius
YannSteph

Sì, e quando utilizzo uno dei metodi di tinta tutto ciò che vedo è il colore. Ho persino impostato l'alfa del colore su 0,5 e vedo ancora solo il colore. Swift 4
Moebius

Ok, applica l'alfa dopo la tinta @Moebius
YannSteph

8

Se stai impostando l'immagine per un pulsante, vai all'ispettore degli attributi e cambia il tipo di pulsante in sistema. Quindi imposta l'immagine e cambia il colore della tinta. Il colore dell'immagine cambierà. Se non è avvenuto, controlla il tipo di pulsante.


7

Swift 4 o 5

extension UIButton{

    func setImageTintColor(_ color: UIColor) {
        let tintedImage = self.imageView?.image?.withRenderingMode(.alwaysTemplate)
        self.setImage(tintedImage, for: .normal)
        self.tintColor = color
    }

}

Uso:

button.setImage(UIImage(named: "image_name"), for: .normal) // You can set image direct from Storyboard
button.setImageTintColor(UIColor.white)

non esiste alcun metodo di setImageTintColor per la visualizzazione del pulsante UI
Wahab Khan Jadon

È un'estensione di UIButton. Ho creato sopra.
Krunal Patel,

6

Se si utilizzano cataloghi di risorse, è possibile impostare la risorsa immagine stessa per il rendering in modalità modello. Dopodiché puoi impostare il tintColor del pulsante in Interface Builder (o nel codice) e dovrebbe richiedere.


Questo è l'approccio migliore se utilizzi la stessa immagine in più posizioni poiché imposti l'immagine in modalità modello solo una volta nel Catalogo risorse.
Jonathan Cabrera

Questo approccio non ha funzionato per me. Quando imposto un PNG come immagine modello e quindi imposto il colore della tinta, l'immagine viene sostituita dal colore della tinta.
Moebius

Questo è l'approccio migliore anche per me. Molte grazie. Semplice facile riutilizzabile ...
Alparslan Selçuk Develioğlu

4

Swift 4

    let origImage = UIImage(named: "check")
    let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
    buttons[0].setImage(tintedImage, for: .normal)
    buttons[0].tintColor = .red

3

Se si utilizzano cataloghi di risorse, è possibile impostare la risorsa immagine stessa per il rendering in modalità modello. Dopodiché puoi impostare il tintColor del pulsante in Interface Builder (o nel codice) e dovrebbe richiedere.


1

Ho trovato l'approccio più semplice di seguito,

Aprire assetcatalog e selezionare l'immagine poi vai a Attributi e cambiare Render Asper Template Imagecome di seguito

inserisci qui la descrizione dell'immagine

Quindi aggiungi il codice sottostante nel pulsante Metodo di azione

yourButton.tintColor = .gray

-1

Swift 4 e 4.2

let img = UIImage.init(named: "buttonName")?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
            btn.setImage(img, for: .normal)
            btn.tintColor = .gray

inserisci qui la descrizione dell'immagine

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.