How can I change image tintColor in iOS and WatchKit
iOS
For an iOS app, in Swift 3, 4 or 5:
theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate)theImageView.tintColor = UIColor.red
For Swift 2:
theImageView.image = theImageView.image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)theImageView.tintColor = UIColor.redColor()
Meanwhile, the modern Objective-C solution is:
theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];[theImageView setTintColor:[UIColor redColor]];
Watchkit
In WatchKit for Apple Watch apps, you can set the tint color for a template image.
- You must add your image to an Asset Catalog in your WatchKit App, and set the image set to be rendered as a Template Image in the Attributes Inspector. Unlike for an iPhone app, you cannot set the template rendering in code in the WatchKit Extension at present.
- Set that image to be used in your WKInterfaceImage in interface builder for your app
- Create an IBOutlet in your WKInterfaceController for the WKInterfaceImage called 'theImage'...
To then set the tint color in Swift 3 or 4:
theImage.setTintColor(UIColor.red)
Swift 2:
theImage.setTintColor(UIColor.redColor())
To then set the tint color in Objective-C:
[self.theImage setTintColor:[UIColor redColor]];
If you use a template image and do not apply a tint colour, the Global Tint for your WatchKit app will be applied. If you have not set a Global Tint, theImage
will be tinted light blue by default when used as a template image.
Here's a category that should do the trick
@interface UIImage(Overlay)@end@implementation UIImage(Overlay)- (UIImage *)imageWithColor:(UIColor *)color1{ UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, 0, self.size.height); CGContextScaleCTM(context, 1.0, -1.0); CGContextSetBlendMode(context, kCGBlendModeNormal); CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); CGContextClipToMask(context, rect, self.CGImage); [color1 setFill]; CGContextFillRect(context, rect); UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage;}@end
so you would do:
theImageView.image = [theImageView.image imageWithColor:[UIColor redColor]];
I had to do this in Swift using an extension
.
I thought I'd share how I did it:
extension UIImage { func imageWithColor(color1: UIColor) -> UIImage { UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) color1.setFill() let context = UIGraphicsGetCurrentContext() as CGContextRef CGContextTranslateCTM(context, 0, self.size.height) CGContextScaleCTM(context, 1.0, -1.0); CGContextSetBlendMode(context, CGBlendMode.Normal) let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect CGContextClipToMask(context, rect, self.CGImage) CGContextFillRect(context, rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() as UIImage UIGraphicsEndImageContext() return newImage }}
Usage:
theImageView.image = theImageView.image.imageWithColor(UIColor.redColor())
Swift 4
extension UIImage { func imageWithColor(color1: UIColor) -> UIImage { UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) color1.setFill() let context = UIGraphicsGetCurrentContext() context?.translateBy(x: 0, y: self.size.height) context?.scaleBy(x: 1.0, y: -1.0) context?.setBlendMode(CGBlendMode.normal) let rect = CGRect(origin: .zero, size: CGSize(width: self.size.width, height: self.size.height)) context?.clip(to: rect, mask: self.cgImage!) context?.fill(rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage! }}
Usage:
theImageView.image = theImageView.image?.imageWithColor(color1: UIColor.red)