Color Tint UIButton Image

IosIphoneUibuttonIos7Uisegmentedcontrol

Ios Problem Overview


I noticed that when I place a white or black UIImage into a UISegmentedControl it automatically color masks it to match the tint of the segmented control. I thought this was really cool, and was wondering if I could do this elsewhere as well. For example, I have a bunch of buttons that have a uniform shape but varied colors. Instead of making a PNG for each button, could I somehow use this color masking to use the same image for all of them but then set a tint color or something to change their actual color?

Ios Solutions


Solution 1 - Ios

As of iOS 7, there is a new method on UIImage to specify the rendering mode. Using the rendering mode UIImageRenderingModeAlwaysTemplate will allow the image color to be controlled by the button's tint color.

Objective-C

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [[UIImage imageNamed:@"image_name"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[button setImage:image forState:UIControlStateNormal]; 
button.tintColor = [UIColor redColor];

Swift

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red

Solution 2 - Ios

As Ric already mentioned in his post you can set the render mode in code, you can also do this directly in the image catalog, see attached image below. Just set the Render As to Template Image

enter image description here

Caveat I have had problems with iOS 7 and this approach. So if you use iOS 7 as well you might want to do it in code as well to be sure, as described here.

Solution 3 - Ios

Custom Buttons appear in their respective image colors. Setting the button type to "System" in the storyboard (or to UIButtonTypeSystem in code), will render the button's image with the default tint color.

Button Type System Renders Icons tinted

(tested on iOS9, Xcode 7.3)

Solution 4 - Ios

You must set the image rendering mode to UIImageRenderingModeAlwaysTemplate in order to have the tintColor affect the UIImage. Here is the solution in Swift:

let image = UIImage(named: "image-name")
let button = UIButton()
button.setImage(image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: .Normal)
button.tintColor = UIColor.whiteColor()

SWIFT 4x

button.setImage(image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate), for: .normal)
button.tintColor = UIColor.blue

Solution 5 - Ios

If you have a custom button with a background image.You can set the tint color of your button and override the image with following .

In assets select the button background you want to set tint color.

In the attribute inspector of the image set the value render as to "Template Image"

enter image description here

Now whenever you setbutton.tintColor = UIColor.red you button will be shown in red.

Solution 6 - Ios

In Swift you can do that like so:

var exampleImage = UIImage(named: "ExampleImage.png")?.imageWithRenderingMode(.AlwaysTemplate)

Then in your viewDidLoad

exampleButtonOutlet.setImage(exampleImage, forState: UIControlState.Normal)

And to modify the color

exampleButtonOutlet.tintColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1) //your color

EDIT Xcode 8 Now you can also just the rendering mode of the image in your .xcassets to Template Image and then you don't need to specifically declare it in the var exampleImage anymore

Solution 7 - Ios

Not sure exactly what you want but this category method will mask a UIImage with a specified color so you can have a single image and change its color to whatever you want.

ImageUtils.h

- (UIImage *) maskWithColor:(UIColor *)color;

ImageUtils.m

-(UIImage *) maskWithColor:(UIColor *)color 
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width;
    CGFloat height = self.size.height;
    CGRect bounds = CGRectMake(0,0,width,height);
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);    
    CGContextFillRect(bitmapContext, bounds);
    
    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage];
    
    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);
    
    return coloredImage;    
}

Import the ImageUtils category and do something like this...

#import "ImageUtils.h"

...

UIImage *icon = [UIImage imageNamed:ICON_IMAGE];

UIImage *redIcon = [icon maskWithColor:UIColor.redColor];
UIImage *blueIcon = [icon maskWithColor:UIColor.blueColor];

Solution 8 - Ios

Swift 4 with customType:

let button = UIButton(frame: aRectHere)
    let buttonImage = UIImage(named: "imageName")
    button.setImage(buttonImage?.withRenderingMode(.alwaysTemplate), for: .normal)
    button.tintColor = .white

Solution 9 - Ios

Swift 3:

This solution could be comfortable if you have already setted your image through xCode interface builder. Basically you have one extension to colorize an image:

extension UIImage {
    public func image(withTintColor color: UIColor) -> UIImage{
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        let context: CGContext = UIGraphicsGetCurrentContext()!
        context.translateBy(x: 0, y: self.size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        context.setBlendMode(CGBlendMode.normal)
        let rect: CGRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
        context.clip(to: rect, mask: self.cgImage!)
        color.setFill()
        context.fill(rect)
        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }
}

Then , you can prepare this UIButton extension to colorize the image for a particular state:

extension UIButton {
    func imageWith(color:UIColor, for: UIControlState) {
        if let imageForState = self.image(for: state) {
            self.image(for: .normal)?.withRenderingMode(.alwaysTemplate)
            let colorizedImage = imageForState.image(withTintColor: color)
            self.setImage(colorizedImage, for: state)
        }
    }
}

Usage:

myButton.imageWith(.red, for: .normal)

P.S. (working good also in table cells, you don't need to call setNeedDisplay() method, the change of the color is immediate due to the UIImage extension..

Solution 10 - Ios

For Xamarin.iOS (C#):

UIButton messagesButton = new UIButton(UIButtonType.Custom);
UIImage icon = UIImage.FromBundle("Images/icon.png");
messagesButton.SetImage(icon.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), UIControlState.Normal);
messagesButton.TintColor = UIColor.White;
messagesButton.Frame = new RectangleF(0, 0, 25, 25);

Solution 11 - Ios

If you want to manually mask your image, here is updated code that works with retina screens

- (UIImage *)maskWithColor:(UIColor *)color
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width * self.scale;
    CGFloat height = self.size.height * self.scale;
    CGRect bounds = CGRectMake(0,0,width,height);
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);
    CGContextFillRect(bitmapContext, bounds);
    
    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:self.scale orientation:self.imageOrientation];
    
    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);
    
    return coloredImage;
}

Solution 12 - Ios

You Should Try

After Setting The Frame

NSArray *arr10 =[NSArray arrayWithObjects:btn1,btn2,nil];
for(UIButton *btn10 in arr10)
{
CAGradientLayer *btnGradient2 = [CAGradientLayer layer];
btnGradient2.frame = btn10.bounds;

btnGradient2.colors = [NSArray arrayWithObjects:
                       (id)[[UIColor colorWithRed:151.0/255.0f green:206.0/255.5 blue:99.0/255.0 alpha:1] CGColor],
                       (id)[[UIColor colorWithRed:126.0/255.0f green:192.0/255.5 blue:65.0/255.0 alpha:1]CGColor],
                       nil];
[btn10.layer insertSublayer:btnGradient2 atIndex:0];

}

Solution 13 - Ios

Swift 3.0

    let image = UIImage(named:"NoConnection")!
    
 warningButton = UIButton(type: .system)        
    warningButton.setImage(image, for: .normal)
    warningButton.tintColor = UIColor.lightText
    warningButton.frame = CGRect(origin: CGPoint(x:-100,y:0), size: CGSize(width: 59, height: 56))
            
    self.addSubview(warningButton)

Solution 14 - Ios

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red

If you are setting UIButton.tintColor by UIColor(r:g:b:alpha:), remember to divide values by 255. Those RGB values should be in between 0 and 1.

Solution 15 - Ios

Change button image or image view tint color Swift :

btn.imageView?.image = btn.imageView?.image?.withRenderingMode(.alwaysTemplate)

btn.imageView?.tintColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)

Solution 16 - Ios

None of above worked for me, because tint was cleared after click. I had to use

button.setImageTintColor(Palette.darkGray(), for: UIControlState())

Solution 17 - Ios

To set white colour of the image(arrow icon) on the button, we're using:

let imageOnButton = UIImage(named: "navForwardArrow")?.imageWithColor(color: UIColor.white)
button.setImage(imageOnButton, for: .normal)

Known issue: The icon looses its white colour while the button is pressed.

Screenshot: enter image description here

Solution 18 - Ios

I had a problem with masking image in highlighted state. I didn't want it to happen. If You have the same problem, check this out: adjustsImageWhenHighlighted = false

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLogan ShireView Question on Stackoverflow
Solution 1 - IosRic SantosView Answer on Stackoverflow
Solution 2 - IoshashierView Answer on Stackoverflow
Solution 3 - IosaucoView Answer on Stackoverflow
Solution 4 - IosNick WargnierView Answer on Stackoverflow
Solution 5 - IosIlker BaltaciView Answer on Stackoverflow
Solution 6 - Ioshenrik-dmgView Answer on Stackoverflow
Solution 7 - IosKirby ToddView Answer on Stackoverflow
Solution 8 - IosaBikisView Answer on Stackoverflow
Solution 9 - IosAlessandro OrnanoView Answer on Stackoverflow
Solution 10 - IosMobile DeveloperView Answer on Stackoverflow
Solution 11 - IosJosh BernfeldView Answer on Stackoverflow
Solution 12 - IosgupthaView Answer on Stackoverflow
Solution 13 - IosJadView Answer on Stackoverflow
Solution 14 - IosFarukView Answer on Stackoverflow
Solution 15 - IosUrvish ModiView Answer on Stackoverflow
Solution 16 - IosSzymon KlimaszewskiView Answer on Stackoverflow
Solution 17 - IosDhananjay MView Answer on Stackoverflow
Solution 18 - IosDaniel SadkaView Answer on Stackoverflow