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.