How to apply a tintColor to a UIImage?
IosObjective CUibuttonUiimageIos Problem Overview
I have a UIImage
that is a small symbol that is all black. The UIImage
is getting set in a custom UIButton
subclass I have. Is it possible to have the image to apply the tintColor
to it, so instead of the black image it changes colors to whatever the tintColor
is?
I'm just trying to avoid creating new assets.
// here I want defaultImageName (that is black) to use the tintColor (that is white)
[self setImage:[UIImage imageNamed:defaultImageName] forState:UIControlStateNormal];
Ios Solutions
Solution 1 - Ios
If you are just supporting iOS 7 you can use tintColor
and UIImageRenderingModeAlwaysTemplate
This article covers that:
https://www.captechconsulting.com/blogs/ios-7-tutorial-series-tint-color-and-easy-app-theming
If you need to support an earlier version you may want to consider this thread
https://stackoverflow.com/questions/1117211/how-would-i-tint-an-image-programatically-on-the-iphone
Solution 2 - Ios
Swift 4, copy-paste solution
@IBOutlet weak var iconImageView: UIImageView!
iconImageView.image = UIImage(imageLiteralResourceName: "myImageName").withRenderingMode(.alwaysTemplate)
iconImageView.tintColor = UIColor.red
Solution 3 - Ios
On iOS 13+ you can use the following:
UIImage(named: "img_name")?.withTintColor(.red)
https://developer.apple.com/documentation/uikit/uiimage/3327300-withtintcolor
Solution 4 - Ios
Try this:
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()
}
For example:
button.setImage(UIImage(systemName: "checkmark.circle")?.tinted(with: .systemGray), for: .normal)
Solution 5 - Ios
Here's how I use tint colors and opacities in IOS 9 with 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
}
Solution 6 - Ios
Why not use image filtering
btn.setImage(image, for: UIControl.State.normal)
btn.setImage(image.disabled, for: UIControl.State.disabled)
Use CoreImage to do image filter
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
}
}
Of course, in Swift 5
Solution 7 - Ios
Swift5 Extension
extension UIImage {
var template: UIImage? {
return self.withRenderingMode(.alwaysTemplate)
}
}
Usage:
-
UIImageView
let imgView = UIImageView() imgView.tintColor = UIColor.red imgView.image = UIImage(named: "IMAGE_NAME_HERE")?.template
-
UIButton
let button = UIButton(type: .custom) button.tintColor = UIColor.red button.setImage(UIImage(named: "IMAGE_NAME_HERE")?.template, for: .normal)
Solution 8 - Ios
Use this simple extension to UIImageView
@IBInspectable var tintedColor: UIColor{
get{
return tintColor
}
set{
image = image?.withRenderingMode(.alwaysTemplate)
tintColor = newValue
}
}