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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19274789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:15:04  来源:igfitidea点击:

How can I change image tintColor in iOS and WatchKit

iosswiftuiimageuicolorwatchkit

提问by chewy

I have an UIImageView called "theImageView", with UIImage in a single color (transparent background) just like the left black heart below. How can I change the tint color of this image programmatically in iOS 7 or above, as per the tint method used in the iOS 7+ Navigation Bar icons?

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

Can this method also work in WatchKit for an Apple Watch app?

这种方法也可以在 Apple Watch 应用的 WatchKit 中使用吗?

enter image description here

在此处输入图片说明

回答by Duncan Babbage

iOS
For an iOS app, in Swift 3, 4 or 5:

iOS
对于 iOS 应用程序,在 Swift 3、4 或 5 中:

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

For Swift 2:

对于 Swift 2:

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

Meanwhile, the modern Objective-C solution is:

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

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


Watchkit
In WatchKit for Apple Watch apps, you can set the tint color for a template image.

Watchkit
在 Apple Watch 应用程序的 WatchKit 中,您可以设置模板图像色调颜色

  1. You must add your image to an Asset Catalog in your WatchKit App, and set the image set to be rendered as a Template Image in the Attributes Inspector. Unlike for an iPhone app, you cannot set the template rendering in code in the WatchKit Extension at present.
  2. Set that image to be used in your WKInterfaceImage in interface builder for your app
  3. Create an IBOutlet in your WKInterfaceController for the WKInterfaceImage called 'theImage'...
  1. 您必须将图像添加到 WatchKit 应用程序中的资产目录,并将图像集设置为在属性检查器中呈现为模板图像。与 iPhone 应用程序不同,目前您无法在 WatchKit 扩展中的代码中设置模板渲染。
  2. 将该图像设置为在您的应用程序的界面构建器中的 WKInterfaceImage 中使用
  3. 在 WKInterfaceController 中为名为“theImage”的 WKInterfaceImage 创建一个 IBOutlet...

To then set the tint color in Swift 3 or 4:

然后在 Swift 3 或 4 中设置色调颜色:

theImage.setTintColor(UIColor.red)

Swift 2:

斯威夫特 2:

theImage.setTintColor(UIColor.redColor())

To then set the tint color in Objective-C:

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

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

If you use a template image and do not apply a tint colour, the Global Tint for your WatchKit app will be applied. If you have not set a Global Tint, theImagewill be tinted light blue by default when used as a template image.

如果您使用模板图像并且不应用色调颜色,则将应用 WatchKit 应用程序的全局色调。如果您没有设置全局色调,theImage当用作模板图像时默认会被染成淡蓝色。

回答by iamamused

Here's a category that should do the trick

这是一个应该可以解决问题的类别

@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

so you would do:

所以你会这样做:

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

回答by fulvio

I had to do this in Swift using an extension.

我必须在 Swift 中使用extension.

I thought I'd share how I did it:

我想我会分享我是如何做到的:

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

Usage:

用法:

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

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

Swift 4

斯威夫特 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!
    }
}

Usage:

用法:

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

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

回答by JerryZhou

In storyboard and image Assets. you can change this two also:

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

Update the Render Mode to Template Image

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

Update the Render Mode to Template Image in Image Assets

将渲染模式更新为图像资产中的模板图像

Update the tint Color in Views.

更新视图中的色调颜色。

Update the tint Color in Views in Views

在视图中更新视图中的色调颜色

回答by YannSteph

Swift 4

斯威夫特 4

Change tint of UIImage SVG / PDF, that work for image with unique color:

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

enter image description hereenter 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
    }
}

Change tint of UIImageView, that work for image with unique color:

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

enter image description hereenter 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

Change tint of UIImagefor picture, use that :

变更色彩的UIImage图片,使用:

enter image description hereenter 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!
    }
}

回答by Puttin

If anyone care a solution without UIImageView:

如果有人关心没有解决方案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
    }
}

回答by Esqarrouth

With 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)

回答by yazh

Try this

尝试这个

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

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

or

或者

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

回答by DairySeeker

For swift 3 purposes

快速 3 目的

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

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

回答by Hakob

iOS

IOS

Solution for doing it from Interface Builder, set templateImage param in keyPathand choose your tint color from IB

从 Interface Builder 执行此操作的解决方案,在 keyPath 中设置 templateImage 参数并从 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
    }
}

}

}