Ändern Sie die Farbe von PNG in Schaltflächen - ios

91

Ich habe eine Reihe von Symbolen erstellt, die transparente weiße PNGs sind:

Geben Sie hier die Bildbeschreibung ein

Und ich möchte sie in andere Farben bringen können. Wie blau, grau usw.

Ich habe festgestellt, dass "geklickt / getippt" automatisch in grau geändert wird. Ich gehe also davon aus, dass ich dieses Grau entweder mit einem Fingertipp oder in seinem normalen Zustand nach Belieben ändern kann:

Geben Sie hier die Bildbeschreibung ein

Was wäre der beste Weg, um dies zu erreichen?

Galaxis
quelle

Antworten:

222

Mit dem folgenden Code wird die Farbtonfarbe für den normalen Status der Schaltfläche festgelegt:

Für Swift 4 und höher:

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

Sie können die Farbtonfarbe entsprechend Ihren Anforderungen ändern, wenn sich der Status für die Schaltfläche ändert.


ältere Versionen

Für Swift 3:

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

Für Swift 2: siehe Revisionsverlauf.

Yuvrajsinh
quelle
Wunderbar! Aber wie kehren Sie zum Originalbild zurück (nicht getönt)?
Marsman
@Marsman Wenn Sie sich meine Lösung ansehen, stellt originaImage das Originalbild und tintedImage die getönte Version des Originalbilds dar. Sie ersetzen also nicht das Originalbild, sondern erstellen eine neue Version davon, und Sie haben zwei Versionen desselben Bildes, als die Sie verwenden können je nach Bedarf
Yuvrajsinh
funktioniert nicht in iOS 11 mit xcode 9.1. Wenn Sie die Farbtonfarbe hinzufügen, wird die Farbe der Bildansicht vollständig geändert.
Vineesh TP
Die verschiedenen Änderungen haben zu Ungenauigkeiten in dieser Antwort geführt.
Eric Aya
13

iOS 7 führte eine Eigenschaft namens tintColor für Ansichten (einschließlich UIImageView) ein. Sie müssen jedoch auch den Rendering-Typ auf dem UIImage festlegen, damit dies Auswirkungen hat.

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

Dies sollte den gewünschten Effekt in einem Standardzustand erzeugen.

JoGoFo
quelle
10

Sie können diese Erweiterung verwenden:

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
        }
    }
}
Ilia Khalyapin
quelle
1
Das funktioniert auch bei mir nicht. Wenn ich diese Methode verwende, sehe ich nur die Farbe, nicht das Bild, das diese Farbe hat.
Möbius
9

Verwenden Sie zum Ändern des Bildtons ( Auswahl , klassisches Bild , Foto ) Folgendes:

Beispielbild: Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

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

}
YannSteph
quelle
Kannst du mir sagen, wie man diese Methoden benutzt, um sie aufzurufen?
Ashmi123
Das funktioniert bei mir überhaupt nicht. Ich habe ein PNG als Bild der Schaltfläche festgelegt. Wenn ich entweder tintPhoto oder tintPicto verwende, funktionieren sie einfach nicht.
Möbius
Fügen Sie Ihr Bild mitRenderingMode (.alwaysTemplate) hinzu? @Moebius
YannSteph
Ja, und wenn ich eine der Farbmethoden verwende, sehe ich nur die Farbe. Ich habe sogar das Alpha der Farbe auf 0,5 gesetzt und sehe immer noch nur die Farbe. Swift 4
Moebius
Ok Alpha nach dem Farbton anwenden @Moebius
YannSteph
8

Wenn Sie das Bild für eine Schaltfläche festlegen, gehen Sie einfach zum Attributinspektor und ändern Sie den Schaltflächentyp in System. Stellen Sie dann das Bild ein und ändern Sie die Farbtonfarbe. Die Farbe des Bildes ändert sich. Wenn dies nicht geschehen ist, überprüfen Sie den Schaltflächentyp.

Milligator
quelle
6

Wenn Sie Asset-Kataloge verwenden, können Sie festlegen, dass das Image-Asset selbst im Vorlagenmodus gerendert wird. Danach können Sie die tintColor der Schaltfläche im Interface Builder (oder im Code) einstellen und es sollte dauern.

Moliveira
quelle
Dies ist der beste Ansatz, wenn Sie dasselbe Bild an mehreren Stellen verwenden, da Sie das Bild im Asset-Katalog nur einmal in den Vorlagenmodus versetzen.
Jonathan Cabrera
Dieser Ansatz hat bei mir nicht funktioniert. Wenn ich ein PNG als Vorlagenbild und dann die Farbtonfarbe einstelle, wird das Bild durch die Farbtonfarbe ersetzt.
Möbius
Dies ist auch für mich der beste Ansatz. Vielen Dank. Einfach leicht wiederverwendbar ...
Alparslan Selçuk Develioğlu
5

Swift 4 oder 5

extension UIButton{

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

}

Verwenden:

button.setImage(UIImage(named: "image_name"), for: .normal) // You can set image direct from Storyboard
button.setImageTintColor(UIColor.white)
Krunal Patel
quelle
Es gibt keine Methode von setImageTintColor für die UIbutton-Ansicht
Wahab Khan Jadon
Es ist eine Erweiterung von UIButton. Ich habe oben erstellt.
Krunal Patel
4

Swift 4

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

Wenn Sie Asset-Kataloge verwenden, können Sie festlegen, dass das Image-Asset selbst im Vorlagenmodus gerendert wird. Danach können Sie die tintColor der Schaltfläche im Interface Builder (oder im Code) einstellen und es sollte dauern.

Ratnesh NS
quelle
0

Ich fand den einfachsten Ansatz unten,

Öffnen assetcatalog und wählen Sie das Bild dann gehen Sie auf Attribute Inspektor und ändern Render Aszu , Template Imagewie unten

Geben Sie hier die Bildbeschreibung ein

Fügen Sie dann den folgenden Code in die Schaltfläche Aktionsmethode ein

yourButton.tintColor = .gray
Kalpa
quelle
-1

Swift 4 und 4.2

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

Geben Sie hier die Bildbeschreibung ein

Akbar Khan
quelle