【问题标题】:How to apply a tintColor to a UIImage?如何将 tintColor 应用于 UIImage?
【发布时间】:2013-11-17 03:40:16
【问题描述】:

我有一个UIImage,它是一个全黑的小符号。 UIImage 设置在我拥有的自定义 UIButton 子类中。是否可以让图像对其应用tintColor,而不是黑色图像,而是将颜色更改为tintColor 的任何颜色?

我只是想避免创建新资产。

// here I want defaultImageName (that is black) to use the tintColor (that is white)
[self setImage:[UIImage imageNamed:defaultImageName] forState:UIControlStateNormal];

【问题讨论】:

  • 这不是链接问题的重复。
  • 请看link在 iOS 和 WatchKit 中更改图像 tintColor

标签: ios objective-c uibutton uiimage


【解决方案1】:

Swift5 扩展

extension UIImage {
    var template: UIImage? {
         return self.withRenderingMode(.alwaysTemplate)
    }
}

用法:

  • UIImageView

    let imgView = UIImageView()
    imgView.tintColor = UIColor.red
    imgView.image = UIImage(named: "IMAGE_NAME_HERE")?.template
    
  • UI按钮

    let button = UIButton(type: .custom)
    button.tintColor = UIColor.red
    button.setImage(UIImage(named: "IMAGE_NAME_HERE")?.template, for: .normal)
    

【讨论】:

    【解决方案2】:

    在 iOS 13+ 上,您可以使用以下内容:

    UIImage(named: "img_name")?.withTintColor(.red)
    

    https://developer.apple.com/documentation/uikit/uiimage/3327300-withtintcolor

    【讨论】:

      【解决方案3】:

      试试这个:

      func tinted(with color: UIColor) -> UIImage? {
          defer { UIGraphicsEndImageContext() }
          UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
          color.set()
          self.withRenderingMode(.alwaysTemplate).draw(in: CGRect(origin: .zero, size: self.size))
          return UIGraphicsGetImageFromCurrentImageContext()
      }
      

      例如:

      button.setImage(UIImage(systemName: "checkmark.circle")?.tinted(with: .systemGray), for: .normal)
      

      【讨论】:

        【解决方案4】:

        使用这个简单的 UIImageView 扩展

        @IBInspectable var tintedColor: UIColor{
            get{
                return tintColor
            }
            set{
                image = image?.withRenderingMode(.alwaysTemplate)
                tintColor = newValue
            }
        }
        

        【讨论】:

          【解决方案5】:

          为什么不使用图像过滤

          btn.setImage(image, for: UIControl.State.normal)
          btn.setImage(image.disabled, for: UIControl.State.disabled)
          

          使用CoreImage做图片过滤

          extension UIImage
          {
              /// Create a grayscale image with alpha channel. Is 5 times faster than grayscaleImage().
              /// - Returns: The grayscale image of self if available.
              var disabled: UIImage?
              {
                  // Create image rectangle with current image width/height * scale
                  let pixelSize = CGSize(width: self.size.width * self.scale, height: self.size.height * self.scale)
                  let imageRect = CGRect(origin: CGPoint.zero, size: pixelSize)
                  // Grayscale color space
                   let colorSpace: CGColorSpace = CGColorSpaceCreateDeviceGray()
          
                      // Create bitmap content with current image size and grayscale colorspace
                  let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
                  if let context: CGContext = CGContext(data: nil, width: Int(pixelSize.width), height: Int(pixelSize.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
                      {
                          // Draw image into current context, with specified rectangle
                          // using previously defined context (with grayscale colorspace)
                          guard let cg = self.cgImage else{
                              return nil
                          }
                          context.draw(cg, in: imageRect)
                          // Create bitmap image info from pixel data in current context
                          if let imageRef: CGImage = context.makeImage(){
                              let bitmapInfoAlphaOnly = CGBitmapInfo(rawValue: CGImageAlphaInfo.alphaOnly.rawValue)
          
                              guard let context = CGContext(data: nil, width: Int(pixelSize.width), height: Int(pixelSize.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfoAlphaOnly.rawValue) else{
                                  return nil
                              }
                              context.draw(cg, in: imageRect)
                              if let mask: CGImage = context.makeImage() {
                                  // Create a new UIImage object
                                  if let newCGImage = imageRef.masking(mask){
                                      // Return the new grayscale image
                                      return UIImage(cgImage: newCGImage, scale: self.scale, orientation: self.imageOrientation)
                                  }
                              }
          
                          }
                      }
          
          
                  // A required variable was unexpected nil
                  return nil
              }
          }
          

          当然,在 Swift 5 中

          【讨论】:

            【解决方案6】:

            Swift 4,复制粘贴解决方案

            @IBOutlet weak var iconImageView: UIImageView!
            iconImageView.image = UIImage(imageLiteralResourceName: "myImageName").withRenderingMode(.alwaysTemplate)
            iconImageView.tintColor = UIColor.red
            

            【讨论】:

            • 警告:我想补充一点,如果您执行任何返回新图像的任务,您将需要再次设置withRenderingMode(.alwaysTemplate)。示例:如果您使用UIGraphicsImageRenderer 调整图像大小。如果您将资产图像设置为模板呈现模式,这也适用。
            【解决方案7】:

            这是我在 IOS 9 中使用 Swift 的色调和不透明度的方法 -

            //apply a color to an image
            //ref - http://stackoverflow.com/questions/28427935/how-can-i-change-image-tintcolor
            //ref - https://www.captechconsulting.com/blogs/ios-7-tutorial-series-tint-color-and-easy-app-theming
            func getTintedImage() -> UIImageView {
            
                var image :UIImage
                var imageView :UIImageView
            
                image = UIImage(named: "someAsset")!
                let size  : CGSize = image.size
                let frame : CGRect = CGRectMake((UIScreen.mainScreen().bounds.width-86)/2, 600, size.width, size.height)
            
                let redCover : UIView = UIView(frame: frame)
            
                redCover.backgroundColor = UIColor.redColor()
                redCover.layer.opacity = 0.75
            
                imageView = UIImageView();
                imageView.image = image.imageWithRenderingMode(UIImageRenderingMode.Automatic)
            
                imageView.addSubview(redCover)
            
                return imageView
            }
            

            【讨论】:

            • 我不喜欢这个解决方案,因为它不会给图像着色。相反,它通过使用第二层并使其中一个(取决于 z 顺序)半透明来降低对比度。您也永远无法达到令人满意的色调饱和度。
            • 很有趣。请发送或在此处发布一些提示或 url 链接以帮助我,然后生成并在此处发布替代解决方案! :)
            【解决方案8】:

            如果您只支持 iOS 7,可以使用 tintColor 和 UIImageRenderingModeAlwaysTemplate

            这篇文章涵盖了:

            https://www.captechconsulting.com/blogs/ios-7-tutorial-series-tint-color-and-easy-app-theming

            如果您需要支持早期版本,您可能需要考虑此线程

            How would I tint an image programmatically on the iPhone?

            【讨论】:

            • 请注意,使用模板可能会影响性能,因为它总是动态合成
            • 您需要设置您的 UIImage 以便它将图像绘制为模板图像,忽略其颜色信息:UIImage *image = [[UIImage imageNamed:@"image.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];。然后将应用 tint 颜色,在 UIImageView 上设置:_imageView.tintColor = [UIColor whiteColor];
            • 不幸的是第一个链接已经死了
            • archive链接
            • 链接已死。请使用正确的详细信息更新此答案
            猜你喜欢
            • 2014-07-14
            • 2021-02-12
            • 1970-01-01
            • 2020-03-04
            • 1970-01-01
            • 1970-01-01
            • 2014-04-05
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多