【问题标题】:Change color of png in buttons - ios更改按钮中 png 的颜色 - ios
【发布时间】:2015-01-25 14:36:20
【问题描述】:

我创建了一组透明的白色 PNG 图标:

我想做的是能够将它们着色为其他颜色。比如蓝色、灰色等。

我注意到“点击/点击”它们会自动变为灰色。所以我假设我可以通过点击或正常状态将灰色更改为我喜欢的任何内容:

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

【问题讨论】:

    标签: ios swift


    【解决方案1】:

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

    对于 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 如果您查看我的解决方案 originaImage 代表原始图像,tintedImage 代表原始图像的着色版本,因此您不是替换原始图像而是创建它的新版本,您将有两个版本您可以根据需要使用相同的图像
    • 无法在带有 xcode 9.1 的 iOS 11 中工作。添加 tint color 时,完全改变了 imageView 的颜色。
    • 各种编辑在此答案中引入了不准确之处。
    【解决方案2】:

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

    打开assetcatalog并选择图像,然后转到属性检查器并将Render As更改为Template Image,如下所示

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

    yourButton.tintColor = .gray
    

    【讨论】:

      【解决方案3】:

      Swift 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 的任何方法
      • 是UIButton的扩展。我已经在上面创建了。
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          要更改图像的色调(pick经典图像照片),请使用:

          示例图片:

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

          【讨论】:

          • 你能告诉我如何使用这些方法意味着如何调用它们吗?
          • 这对我来说根本不起作用。我有一个 PNG 设置为按钮的图像。当我使用 tintPhoto 或 tintPicto 时,它们都不起作用。
          • 你用 RenderingMode(.alwaysTemplate) 添加你的图像吗? @Moebius
          • 是的,当我使用任何一种着色方法时,我看到的只是颜色。我什至将颜色的 alpha 设置为 0.5,但我仍然只看到颜色。斯威夫特 4
          • 确定在@Moebius 着色后应用 alpha
          【解决方案7】:

          你可以使用这个扩展:

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

          【讨论】:

          • 这对我也不起作用。当我使用这种方法时,我看到的只是颜色,而不是带有那种颜色的图像。
          【解决方案8】:

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

          【讨论】:

          • 如果您在多个地方使用相同的图像,这是最好的方法,因为您只在资产目录中将图像设置为模板模式一次。
          • 这种方法对我不起作用。当我将 PNG 设置为模板图像,然后设置色调颜色时,图像会被色调颜色替换。
          • 这对我来说也是最好的方法。非常感谢。简单易重复使用...
          【解决方案9】:

          斯威夫特 4

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

          【讨论】:

            【解决方案10】:

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

            【讨论】:

              【解决方案11】:

              Swift 4 和 4.2

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2020-08-03
                • 2014-07-11
                相关资源
                最近更新 更多