更改按钮中png的颜色-iOS


93

我有一组创建的图标,它们是透明的白色PNG:

在此处输入图片说明

而我想做的就是能够将它们着色为其他颜色。例如蓝色,灰色等

我注意到,“单击/点击”它们会自动变为灰色。因此,我想我可以通过点击或将其正常状态更改为我喜欢的灰色:

在此处输入图片说明

实现这一目标的最佳方法是什么?

Answers:


225

以下代码将为按钮的正常状态设置颜色:

对于Swift 4和更高版本:

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

当按钮的状态更改时,您可以根据需要更改色调颜色。


旧版本

对于Swift 3:

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

对于Swift 2:请参阅修订历史记录。


精彩!但是,如何恢复为原始图像(未着色)?
Marsman

@Marsman,如果您查看我的解决方案,originaImage代表原始图像,tintedImage代表原始图像的着色版本,因此您不是在替换原始图像,而是为其创建新版本,并且将有两个相同版本的图像可以用作根据您的需要
Yuvrajsinh 2016年

在带有xcode 9.1的iOS 11中不起作用。当添加色调颜色时,它会完全更改imageView的颜色。
Vineesh TP

各种编辑在此答案中引入了不准确之处。
埃里克·艾雅

13

iOS 7为视图(包括UIImageView)引入了名为tintColor的属性。但是,您还需要在UIImage上设置渲染类型,以使其生效。

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

这将在默认状态下产生您想要的效果。


10

您可以使用以下扩展名:

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
这对我也不起作用。当我使用这种方法时,我所看到的只是颜色,而不是带有该颜色的图像。
Moebius

9

用于改变图像的色彩(选择古典图像照片),请使用:

示例图片: 在此处输入图片说明 在此处输入图片说明

迅捷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

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

}

您能告诉我如何使用此方法意味着如何调用它们吗?
ashmi123

这对我根本不起作用。我将PNG设置为按钮的图像。当我使用tintPhoto或tintPicto时,它们根本不起作用。
Moebius

您是否使用RenderingMode(.alwaysTemplate)添加图像?@Moebius
YannSteph

是的,当我使用任何一种着色方法时,我所看到的只是颜色。我什至将颜色的Alpha设置为0.5,但我仍然只能看到颜色。斯威夫特4号
Moebius

可以在色调@Moebius之后应用Alpha
YannSteph

8

如果要为按钮设置图像,只需转到属性检查器并将按钮类型更改为system。然后设置图像并更改色调颜色。图像的颜色将改变。如果没有发生,请检查按钮类型。


7

斯威夫特4或5

extension UIButton{

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

}

用:

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

UIbutton视图没有setImageTintColor的任何方法
Wahab Khan Jadon

它是UIButton的扩展。我已经在上面创建了。
Krunal Patel

6

如果使用资产目录,则可以将图像资产本身设置为以模板模式呈现。之后,您可以在Interface Builder(或代码)中设置按钮的tintColor,它应该使用。


如果要在多个位置使用同一图像,这是最好的方法,因为在资产目录中一次只能将图像设置为模板模式。
乔纳森·卡布雷拉

这种方法对我不起作用。当我将PNG设置为模板图像,然后设置色调颜色时,该图像将替换为色调颜色。
Moebius

这对我也是最好的方法。非常感谢。简单易用,可重复使用...
AlparslanSelçukDevelioğlu

4

斯威夫特4

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

3

如果使用资产目录,则可以将图像资产本身设置为以模板模式呈现。之后,您可以在Interface Builder(或代码)中设置按钮的tintColor,它应该使用。


1

我在下面找到了最简单的方法,

打开assetcatalog并选择图像,然后去属性检查器和变革Render As,以Template Image如下

在此处输入图片说明

然后在按钮Action方法中添加以下代码

yourButton.tintColor = .gray

-1

斯威夫特4和4.2

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

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.