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

这个方法也适用于WatchKit的Apple Watch应用程序吗?


当前回答

斯威夫特4

改变UIImage SVG / PDF的色调,适用于颜色独特的图像:

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的色调,这适用于具有独特颜色的图像:

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的色调,使用它:

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

其他回答

子类,也可以从代码和接口生成器中使用:

@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

利用Swift中的扩展:-

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)

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

extension UIImageView {

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

用法:

myImageView.setImageTintColor(.systemBlue)

在iOS 13及以上版本中,你可以简单地使用

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

自iOS 13以来,UIImage有一个原生方法

let image = yourImage.withTintColor(.systemRed)