如何在iOS和WatchKit中更改图像tintColor

时间:2013-10-09 14:25:33

标签: ios swift uiimage uicolor watchkit

我有一个名为“theImageView”的UIImageView,UIImage为单色(透明背景),就像下面左边的黑色心脏一样。如何根据iOS 7+导航栏图标中使用的色调方法在iOS 7或更高版本中以编程方式更改此图像的色调颜色?

此方法是否也可以在WatchKit中用于Apple Watch应用程序?

enter image description here

25 个答案:

答案 0 :(得分:661)

<强>的iOS
对于iOS应用程序,在Swift 3或4中:

theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate)
theImageView.tintColor = UIColor.red

斯威夫特2:

theImageView.image = theImageView.image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
theImageView.tintColor = UIColor.redColor()

同时,现代的Objective-C解决方案是:

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];

<强> Watchkit
在WatchKit for Apple Watch应用程序中,您可以设置tint color for a template image

  1. 您必须将图像添加到WatchKit应用程序中的资产目录,并将图像集设置为在“属性”检查器中呈现为模板图像。与iPhone应用程序不同,您目前无法在WatchKit Extension中的代码中设置模板渲染。
  2. 在您的应用的界面构建器中设置要在WKInterfaceImage中使用的图像
  3. 在WKInterfaceController中为名为'theImage'的WKInterfaceImage创建一个IBOutlet ......
  4. 然后在Swift 3或4中设置色调颜色:

    theImage.setTintColor(UIColor.red)
    

    斯威夫特2:

    theImage.setTintColor(UIColor.redColor())
    

    然后在Objective-C中设置色调颜色:

    [self.theImage setTintColor:[UIColor redColor]];
    

    如果您使用模板图像并且不应用色调颜色,则将应用WatchKit应用程序的全局色调。如果您尚未设置全局色调,则theImage在用作模板图像时默认会浅蓝色。

答案 1 :(得分:119)

这是一个应该做的技巧

@interface UIImage(Overlay)
@end

@implementation UIImage(Overlay)

- (UIImage *)imageWithColor:(UIColor *)color1
{
        UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(context, 0, self.size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, kCGBlendModeNormal);
        CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
        CGContextClipToMask(context, rect, self.CGImage);
        [color1 setFill];
        CGContextFillRect(context, rect);
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return newImage;
}
@end

所以你会这样做:

theImageView.image = [theImageView.image imageWithColor:[UIColor redColor]];

答案 2 :(得分:93)

我必须使用extension在Swift中执行此操作。

我以为我会分享我是如何做到的:

extension UIImage {
    func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext() as CGContextRef
        CGContextTranslateCTM(context, 0, self.size.height)
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, CGBlendMode.Normal)

        let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect
        CGContextClipToMask(context, rect, self.CGImage)
        CGContextFillRect(context, rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext() as UIImage
        UIGraphicsEndImageContext()

        return newImage
    }
}

用法:

theImageView.image = theImageView.image.imageWithColor(UIColor.redColor())

Swift 4

extension UIImage {
    func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext()
        context?.translateBy(x: 0, y: self.size.height)
        context?.scaleBy(x: 1.0, y: -1.0)
        context?.setBlendMode(CGBlendMode.normal)

        let rect = CGRect(origin: .zero, size: CGSize(width: self.size.width, height: self.size.height))
        context?.clip(to: rect, mask: self.cgImage!)
        context?.fill(rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }
}

用法:

theImageView.image = theImageView.image?.imageWithColor(color1: UIColor.red)

答案 3 :(得分:85)

在故事板和图像资产中。你也可以改变这两个:

将渲染模式更新为模板图像

Update the Render Mode to Template Image in Image Assets

更新视图中的色调颜色。

Update the tint Color in Views in Views

答案 4 :(得分:31)

Swift 4

更改 UIImage SVG / PDF 的色调,适用于具有独特色彩的图像

enter image description here enter image description here

import Foundation

// MARK: - UIImage extensions

public extension UIImage {

    //
    /// Tint Image
    ///
    /// - Parameter fillColor: UIColor
    /// - Returns: Image with tint color
    func tint(with fillColor: UIColor) -> UIImage? {
        let image = withRenderingMode(.alwaysTemplate)
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        fillColor.set()
        image.draw(in: CGRect(origin: .zero, size: size))

        guard let imageColored = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }

        UIGraphicsEndImageContext()
        return imageColored
    }
}

更改 UIImageView 的色调,适用于具有独特色彩的图像

enter image description here enter image description here

let imageView = UIImageView(frame: CGRect(x: 50, y: 50, width: 50, height: 50))
imageView.image = UIImage(named: "hello.png")!.withRenderingMode(.alwaysTemplate)
imageView.tintColor = .yellow

图片更改 UIImage 的色调,请使用:

enter image description here enter image description here

import Foundation

// MARK: - Extensions UIImage

public extension UIImage {

    /// Tint, Colorize image with given tint color
    /// This is similar to Photoshop's "Color" layer blend mode
    /// 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
    ///
    /// - Parameter TintColor: Tint color
    /// - Returns:  Tinted image
    public func tintImage(with fillColor: 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)
            fillColor.setFill()
            context.fill(rect)

            // mask by alpha values of original image
            context.setBlendMode(.destinationIn)
            context.draw(context.makeImage()!, 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!
    }
}

答案 5 :(得分:31)

如果有人关心没有UIImageView的解决方案:

// (Swift 3)
extension UIImage {
    func tint(with color: UIColor) -> UIImage {
        var image = withRenderingMode(.alwaysTemplate)
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        color.set()

        image.draw(in: CGRect(origin: .zero, size: size))
        image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }
}

答案 6 :(得分:17)

使用Swift

let commentImageView = UIImageView(frame: CGRectMake(100, 100, 100, 100))
commentImageView.image = UIImage(named: "myimage.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
commentImageView.tintColor = UIColor.blackColor()
addSubview(commentImageView)

答案 7 :(得分:4)

试试这个

http://robots.thoughtbot.com/designing-for-ios-blending-modes

- (void)viewDidLoad
{
[super viewDidLoad];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 300, 50)];
label.numberOfLines = 0;
label.font = [UIFont systemFontOfSize:13];
label.text = @"These checkmarks use the same gray checkmark image with a tintColor applied to the image view";
[self.view addSubview:label];

[self _createImageViewAtY:100 color:[UIColor purpleColor]];
}

- (void)_createImageViewAtY:(int)y color:(UIColor *)color {
UIImage *image = [[UIImage imageNamed:@"gray checkmark.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect frame = imageView.frame;
frame.origin.x = 100;
frame.origin.y = y;
imageView.frame = frame;

if (color)
    imageView.tintColor = color;

[self.view addSubview:imageView];
}

答案 8 :(得分:4)

为了迅速的目的

theImageView.image = theImageView.image!.withRenderingMode(.alwaysTemplate) theImageView.tintColor = UIColor.red

答案 9 :(得分:2)

在iOS 13及更高版本中,您只需使用

let image = UIImage(named: "Heart")?.withRenderingMode(.alwaysTemplate)
if #available(iOS 13.0, *) {
   imageView.image = image?.withTintColor(UIColor.white)
}

答案 10 :(得分:2)

<强>的iOS

从Interface Builder set templateImage param in keyPath执行此操作的解决方案,并从IB

中选择您的色调颜色
extension UIImageView {

// make template image with tint color
var templateImage: Bool {
    set {
        if newValue, let image = self.image {
            let newImage = image.withRenderingMode(.alwaysTemplate)
            self.image = newImage
        }
    } get {
        return false
    }
}

}

答案 11 :(得分:1)

用于着色UIButton的图像

let image1 = "ic_shopping_cart_empty"
btn_Basket.setImage(UIImage(named: image1)?.withRenderingMode(.alwaysTemplate), for: .normal)
btn_Basket.setImage(UIImage(named: image1)?.withRenderingMode(.alwaysTemplate), for: .selected)
btn_Basket.imageView?.tintColor = UIColor(UIColor.Red)

答案 12 :(得分:1)

在Swift中利用Extension: -

extension UIImageView {
    func changeImageColor( color:UIColor) -> UIImage
    {
        image = image!.withRenderingMode(.alwaysTemplate)
        tintColor = color
        return image!
    }
}

   //Change color of logo 
   logoImage.image =  logoImage.changeImageColor(color: .red)

enter image description here

答案 13 :(得分:0)

自iOS 13起,就有一个UIImage的本地方法

{ pattern: {}}

答案 14 :(得分:0)

雨燕5

使用背景和填充颜色重画图像

extension UIImage {
  func withBackground(color: UIColor, fill fillColor: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(size, true, scale)
    
    guard let ctx = UIGraphicsGetCurrentContext(), let image = cgImage else { return self }
    defer { UIGraphicsEndImageContext() }
    
    ctx.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: size.height))
    
    let rect = CGRect(origin: .zero, size: size)
    
    // draw background
    ctx.setFillColor(color.cgColor)
    ctx.fill(rect)
    
    // draw image with fill color
    ctx.clip(to: rect, mask: image)
    ctx.setFillColor(fillColor.cgColor)
    ctx.fill(rect)
    
    return UIGraphicsGetImageFromCurrentImageContext() ?? self
  }
}

答案 15 :(得分:0)

此外,对于以上答案,在iOS 13及更高版本中,有一种干净的方法

static

答案 16 :(得分:0)

let navHeight = self.navigationController?.navigationBar.frame.height;
let menuBtn = UIButton(type: .custom)
menuBtn.frame = CGRect(x: 0, y: 0, width: 45, height: navHeight!)     
menuBtn.setImage(UIImage(named:"image_name")!.withRenderingMode(.alwaysTemplate), for: .normal)        
menuBtn.tintColor = .black

答案 17 :(得分:0)

这是一个适用于 Swift 5 的简单扩展:

extension UIImageView {

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

用法:

myImageView.setImageTintColor(.systemBlue)

答案 18 :(得分:0)

如果您有SVG图片的ID,则可以根据ID填充颜色。

    let image = SVGKImage(named: "iconName")
    let svgIMGV = SVGKFastImageView(frame: self.imgView.frame)
         svgIMGV.image = image
          svgIMGV.fillTintColor(colorImage: UIColor.red, iconID: "Bank")
// Add in extension SVGKImageView
extension SVGKImageView {
 func fillTintColor(colorImage: UIColor, iconID: String) {
        if self.image != nil && self.image.caLayerTree != nil {
            print(self.image.caLayerTree.sublayers)
            guard let sublayers = self.image.caLayerTree.sublayers else { return }
            fillRecursively(sublayers: sublayers, color: colorImage, iconID: iconID)
        }
    }

     private func fillRecursively(sublayers: [CALayer], color: UIColor, iconID: String, hasFoundLayer: Bool) {
        var isLayerFound = false
        for layer in sublayers {
            if let l = layer as? CAShapeLayer {

                print(l.name)                
                //IF you want to color the specific shapelayer by id else remove the l.name  == "myID"  validation
                if let name =  l.name,  hasFoundLayer == true && name == "myID" {
                    self.colorThatImageWIthColor(color: color, layer: l)
                    print("Colouring FInished")
                }
            } else {
                if layer.name == iconID {
                    if let innerSublayer = layer.sublayers as? [CAShapeLayer] {
                        fillRecursively(sublayers: innerSublayer, color: color, iconID: iconID, hasFoundLayer: true )
                        print("FOund")
                    }
                } else {
                    if let l = layer as? CALayer, let sub = l.sublayers {
                        fillRecursively(sublayers: sub, color: color, iconID: iconID, hasFoundLayer: false)
                    }
                }
            }

        }
    }

    func colorThatImageWIthColor(color: UIColor, layer: CAShapeLayer) {
        if layer.strokeColor != nil {
            layer.strokeColor = color.cgColor
        }
        if layer.fillColor != nil {
            layer.fillColor = color.cgColor
        }
    }

}

或查看此示例。

https://github.com/ravisfortune/SVGDEMO

答案 19 :(得分:0)

profileImageView.image = theImageView.image!.withRenderingMode(.alwaysTemplate)
profileImageView.tintColor = UIColor.green

OR

首先在图像资源中选择特定图像,然后选择红色为模板而不是默认,并在该写入行之后。 profileImageView.tintColor = UIColor.green

答案 20 :(得分:0)

fuzz

的Swift 3版扩展答案
func imageWithColor(color: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    color.setFill()

    let context = UIGraphicsGetCurrentContext()! as CGContext
    context.translateBy(x: 0, y: self.size.height)
    context.scaleBy(x: 1.0, y: -1.0);
    context.setBlendMode(.normal)

    let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) as CGRect
    context.clip(to: rect, mask: self.cgImage!)
    context.fill(rect)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage
    UIGraphicsEndImageContext()

    return newImage
}

答案 21 :(得分:0)

这是我的UIImage扩展,您可以直接将changeTintColor函数用于图像。

let image = UIImage(named: "sample_image")
imageView.image = image.changeTintColor(color: UIColor.red)

像这样的用法

changeColor

您可以使用更改// Connection to DB $konek = new PDO('mysql:host=localhost;$db', $User, $Password); if ($db){ echo('Connected to: "'.$db.'"'); } 功能更改图像颜色

答案 22 :(得分:0)

可以从代码和Interface Builder中使用的子类:

@implementation TintedImageView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self setup];
    }
    return self;
}

-(void)setup {
    self.image = [self.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
}

@end

答案 23 :(得分:0)

  

如果您有替换清除按钮的图像,可以在Swift 3中使用它

var socket = io();
var stream = ss.createStream();
ss(socket).emit('blatin', stream);

var imageBuffer = new ss.Buffer(256*256*4);
function sendBlat() {
    imageBuffer.set(ctx.getImageData(0,0,canvas.width,canvas.height).data);
    stream.write(imageBuffer);
    return false;
}

答案 24 :(得分:0)

现在我使用这个基于Duncan Babbage响应的方法:

+ (UIImageView *) tintImageView: (UIImageView *)imageView withColor: (UIColor*) color{
    imageView.image = [imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    [imageView setTintColor:color];
    return imageView;
}