Ubah warna png di tombol - ios

95

Saya punya satu set ikon yang saya buat yang merupakan PNG putih transparan:

masukkan deskripsi gambar di sini

Dan yang ingin saya lakukan adalah bisa mewarnai mereka dengan warna lain. Seperti biru, abu-abu, dll.

Saya perhatikan bahwa 'diklik / disadap' berubah secara otomatis menjadi abu-abu. Jadi saya berasumsi saya bisa mengubah abu-abu itu menjadi apa pun yang saya suka baik dengan ketukan atau keadaan normalnya:

masukkan deskripsi gambar di sini

Apa cara terbaik untuk mencapai ini?

Galaksi
sumber

Jawaban:

231

Kode berikut akan mengatur warna tint untuk keadaan normal tombol:

Untuk Swift 4 dan yang lebih baru:

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

Anda dapat mengubah warna tint sesuai dengan kebutuhan Anda saat status berubah untuk tombol.


Versi yang lebih lama

Untuk Swift 3:

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

Untuk Swift 2: lihat riwayat revisi.

Yuvrajsinh
sumber
Hebat! Tapi bagaimana Anda kembali ke gambar asli (tidak diwarnai)?
Marsman
@Marsman jika Anda melihat solusi saya originaImage mewakili gambar asli dan tintedImage mewakili versi berwarna dari gambar asli, jadi Anda tidak mengganti Gambar asli tetapi membuat versi baru dan Anda akan memiliki dua versi gambar yang sama yang dapat Anda gunakan sebagai sesuai kebutuhan Anda
Yuvrajsinh
tidak berfungsi di iOS 11 dengan xcode 9.1. Saat menambahkan warna tint, itu benar-benar mengubah warna imageView.
Vineesh TP
Berbagai pengeditan telah menyebabkan ketidakakuratan dalam jawaban ini.
Eric Aya
13

iOS 7 memperkenalkan properti yang disebut tintColor untuk tampilan (termasuk UIImageView). Namun Anda juga perlu menyetel jenis rendering pada UIImage agar ini memiliki efek apa pun.

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

Ini akan menghasilkan efek yang Anda kejar dalam keadaan default.

JoGoFo
sumber
10

Anda dapat menggunakan ekstensi ini:

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
sumber
2
Ini juga tidak berhasil untuk saya. Ketika saya menggunakan metode ini, yang saya lihat hanyalah warnanya, bukan gambar yang diwarnai dengan warna itu.
Moebius
9

Untuk mengubah warna gambar ( pilih , gambar klasik , foto ) gunakan:

Contoh gambar: masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Cepat 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

Cepat 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
sumber
dapatkah kamu memberitahuku bagaimana menggunakan metode ini berarti bagaimana memanggil mereka?
ashmi123
Ini tidak bekerja sama sekali untuk saya. Saya memiliki set PNG sebagai gambar tombol. Saat saya menggunakan tintPhoto atau tintPicto, keduanya tidak berfungsi.
Moebius
apakah Anda menambahkan gambar Anda denganRenderingMode (.alwaysTemplate)? @Oebius
Yanneph
Ya, dan ketika saya menggunakan salah satu metode rona yang saya lihat hanyalah warnanya. Saya bahkan mengatur alpha warna menjadi 0,5 dan saya masih melihat warnanya saja. Swift 4
Moebius
Oke, terapkan alfa setelah warna @Moebius
YannSteph
9

Jika Anda menyetel gambar untuk sebuah tombol, buka saja inspektur atribut dan ubah jenis tombol ke sistem. Kemudian atur gambar dan ubah warna tint. Warna gambar akan berubah. Jika tidak berhasil, periksa jenis tombolnya.

Miligator
sumber
9

Swift 4 atau 5

extension UIButton{

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

}

Menggunakan:

button.setImage(UIImage(named: "image_name"), for: .normal) // You can set image direct from Storyboard
button.setImageTintColor(UIColor.white)
Krunal Patel
sumber
tidak ada metode setImageTintColor untuk tampilan tombol UI
Wahab Khan Jadon
Ini merupakan perpanjangan dari UIButton. Saya telah membuat di atas.
Krunal Patel
6

Jika Anda menggunakan katalog aset, Anda dapat menyetel aset gambar itu sendiri untuk dirender dalam mode template. Setelah itu Anda dapat mengatur tintColor tombol di Interface Builder (atau dalam kode) dan itu harus dilakukan.

moliveira
sumber
Ini adalah pendekatan terbaik jika Anda menggunakan gambar yang sama di banyak tempat karena Anda hanya menyetel gambar ke mode template satu kali di Katalog Aset.
Jonathan Cabrera
Pendekatan ini tidak berhasil untuk saya. Saat saya mengatur PNG sebagai gambar template dan kemudian mengatur warna tint, gambar diganti dengan warna tint.
Moebius
Ini juga merupakan pendekatan terbaik bagi saya. Terima kasih banyak. Sederhana dan mudah digunakan kembali ...
Alparslan Selçuk Develioğlu
4

Cepat 4

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

Jika Anda menggunakan katalog aset, Anda dapat menyetel aset gambar itu sendiri untuk dirender dalam mode template. Setelah itu Anda dapat mengatur tintColor tombol di Interface Builder (atau dalam kode) dan itu harus dilakukan.

Ratnesh NS
sumber
3

Saya menemukan pendekatan termudah di bawah ini,

Terbuka assetcatalog dan pilih gambar kemudian pergi ke atribut inspektur dan perubahan Render Asuntuk Template Imageseperti di bawah ini

masukkan deskripsi gambar di sini

Kemudian tambahkan kode di bawah ini dalam metode Tindakan tombol

yourButton.tintColor = .gray
kalpa
sumber
-1

Swift 4 dan 4.2

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

masukkan deskripsi gambar di sini

Akbar Khan
sumber