Düğmelerdeki png rengini değiştirme - iOS


95

Şeffaf beyaz PNG'ler olan, oluşturduğum bir dizi simgem var:

görüntü açıklamasını buraya girin

Ve yapmak istediğim şey onları başka renklere boyayabilmek. Mavi, gri vb.

'Tıklandığında / dokunduğunda' otomatik olarak griye döndüklerini fark ettim. Bu yüzden, o griyi bir dokunuşla veya normal durumuna istediğim şekilde değiştirebileceğimi varsayıyorum:

görüntü açıklamasını buraya girin

Bunu başarmanın en iyi yolu ne olabilir?

Yanıtlar:


231

Aşağıdaki kod, normal düğme durumu için renk tonu ayarlayacaktır:

Swift 4 ve daha yenisi için:

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

Düğme için durum değiştiğinde ihtiyacınıza göre ton rengini değiştirebilirsiniz.


eski versiyonlar

Swift 3 için:

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

Swift 2 için: revizyon geçmişine bakın.


Olağanüstü! Ancak orijinal görüntüye (renksiz) nasıl geri dönersiniz?
Marsman

@Marsman benim çözümüme bakarsanız originaImage orijinal görüntüyü temsil eder ve tintedImage orijinal görüntünün renkli halini temsil eder, bu nedenle orijinal Görüntüyü değiştirmiyor, yeni bir sürümünü oluşturuyorsunuz ve aynı görüntünün iki sürümüne sahip olacaksınız. ihtiyacınıza göre
Yuvrajsinh

iOS 11'de xcode 9.1 ile çalışmıyor. Renk tonu rengi eklendiğinde, tamamen imageView rengini değiştirir.
Vineesh TP

Çeşitli düzenlemeler bu yanıtta yanlışlıklar ortaya çıkarmıştır.
Eric Aya

13

iOS 7, görünümler için tintColor adlı bir özellik sunmuştur (UIImageView dahil). Bununla birlikte, bunun herhangi bir etkiye sahip olması için UIImage üzerinde işleme türünü de ayarlamanız gerekir.

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

Bu, varsayılan durumda peşinde olduğunuz etkiyi yaratmalıdır.


10

Bu uzantıyı kullanabilirsiniz:

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

2
Bu benim için de çalışmıyor. Bu yöntemi kullandığımda, gördüğüm tek şey renk, o renge renk veren görüntü değil.
Moebius

9

Görüntünün renk tonunu değiştirmek için ( çekme , klasik görüntü , fotoğraf ) şunları kullanın:

Örnek resim: görüntü açıklamasını buraya girin görüntü açıklamasını buraya girin

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

Hızlı 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!
    }

}

Bana bu yöntemleri nasıl arayacağımı söyleyebilir misin?
ashmi123

Bu benim için hiç çalışmıyor. Düğmenin resmi olarak bir PNG ayarım var. TintPhoto veya tintPicto kullandığımda, sadece çalışmıyorlar.
Moebius

ResminiziRenderingMode (.alwaysTemplate) ile eklediniz mi? @Moebius
YannSteph

Evet ve renk tonu yöntemlerinden birini kullandığımda gördüğüm tek şey renk. Rengin alfasını bile 0,5 olarak ayarladım ve hala sadece rengi görüyorum. Swift 4
Moebius

Tamam tondan sonra alfa uygulayın @Moebius
YannSteph

9

Bir düğme için görüntüyü ayarlıyorsanız, öznitelik denetçisine gidin ve düğme türünü sistem olarak değiştirin. Ardından görüntüyü ayarlayın ve ton rengini değiştirin. Görüntünün rengi değişecektir. Eğer gerçekleşmediyse, düğme tipini kontrol edin.


9

Swift 4 veya 5

extension UIButton{

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

}

Kullanım:

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

UIbutton görünümü için herhangi bir setImageTintColor yöntemi yoktur
Wahab Khan Jadon

UIButton'un bir uzantısıdır. Yukarıda yarattım.
Krunal Patel

6

Varlık katalogları kullanıyorsanız, görüntü varlığının kendisini şablon modunda işlenecek şekilde ayarlayabilirsiniz. Bundan sonra Interface Builder'da (veya kodda) butonun tintColor'unu ayarlayabilirsiniz ve alması gerekir.


Varlık Kataloğu'nda görüntüyü şablon moduna yalnızca bir kez ayarladığınız için, aynı görüntüyü birden çok yerde kullanıyorsanız bu en iyi yaklaşımdır.
Jonathan Cabrera

Bu yaklaşım benim için işe yaramadı. Bir PNG'yi şablon görüntüsü olarak ayarladığımda ve ardından renk tonu rengini ayarladığımda, görüntü renk tonu rengiyle değiştiriliyor.
Moebius

Bu benim için de en iyi yaklaşım. Çok teşekkürler. Basit, kolay tekrar kullanılabilir ...
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

Varlık katalogları kullanıyorsanız, görüntü varlığının kendisini şablon modunda işlenecek şekilde ayarlayabilirsiniz. Bundan sonra Interface Builder'da (veya kodda) butonun tintColor'unu ayarlayabilirsiniz ve alması gerekir.


3

En kolay yaklaşımı aşağıda buldum,

Açık assetcatalog ve görüntüyü seçmek sonra gidip nitelikleri müfettişi ve değişim Render Asiçin Template Imageaşağıda

görüntü açıklamasını buraya girin

Ardından aşağıdaki kodu düğme Eylem yöntemine ekleyin

yourButton.tintColor = .gray

-1

Swift 4 ve 4.2

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

görüntü açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.