【发布时间】:2015-01-25 14:36:20
【问题描述】:
我创建了一组透明的白色 PNG 图标:
我想做的是能够将它们着色为其他颜色。比如蓝色、灰色等。
我注意到“点击/点击”它们会自动变为灰色。所以我假设我可以通过点击或正常状态将灰色更改为我喜欢的任何内容:
实现这一目标的最佳方法是什么?
【问题讨论】:
我创建了一组透明的白色 PNG 图标:
我想做的是能够将它们着色为其他颜色。比如蓝色、灰色等。
我注意到“点击/点击”它们会自动变为灰色。所以我假设我可以通过点击或正常状态将灰色更改为我喜欢的任何内容:
实现这一目标的最佳方法是什么?
【问题讨论】:
以下代码将为按钮的正常状态设置色调颜色:
对于 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: 查看修订历史记录。
【讨论】:
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)
【讨论】:
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];
这应该会在默认状态下产生您想要的效果。
【讨论】:
如果您要为按钮设置图像,只需转到属性检查器并将按钮类型更改为系统。然后设置图像并更改色调颜色。图像的颜色会发生变化。如果没有发生,请检查按钮类型。
【讨论】:
要更改图像的色调(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!
}
}
【讨论】:
你可以使用这个扩展:
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
}
}
}
【讨论】:
如果您使用资产目录,您可以将图像资产本身设置为以模板模式呈现。之后,您可以在 Interface Builder(或在代码中)设置按钮的 tintColor ,它应该采取。
【讨论】:
斯威夫特 4
let origImage = UIImage(named: "check")
let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
buttons[0].setImage(tintedImage, for: .normal)
buttons[0].tintColor = .red
【讨论】:
如果您使用资产目录,您可以将图像资产本身设置为以模板模式呈现。之后,您可以在 Interface Builder(或在代码中)设置按钮的 tintColor ,它应该采取。
【讨论】: