When I make icons for a UITabBar, it applies a gradient to the images. I need to know how to prevent it from having this gradient.
7 Answers
Apple added tab bar customization in iOS 5, and now this kind of stuff is trivial. Prior to this it was a huge hack, and not recommended.
Here's how to do a completely custom tab bar:
// custom icons
UITabBarItem *item = [[UITabBarItem alloc] init];
item.title = @"foo";
// setting custom images prevents the OS from applying a tint color
[item setFinishedSelectedImage:[UIImage imageNamed:@"tab1_active.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"tab1_image_deselected.png"]];
tab1ViewController.tabBarItem = item;
// tab bar
// set background image - will be used instead of glossy black
tabBarController.tabBar.backgroundImage = [UIImage imageNamed:@"tab_bar_bg.png"];
// optionally set the tint color - setting this ti nil will result in the standard, blue tint color. tint color is ignored when custom icons are set as above.
tabBarController.tabBar.selectedImageTintColor = nil;
// remove the highlight around the selected tab - or provide an alternate highlight image. If you don't do this the iOS default is to draw a highlighted box beneath the selected tab icon.
tabBarController.tabBar.selectionIndicatorImage = [[UIImage alloc] init];

- 6,843
- 53
- 40
-
The above mentioned code snippet is not working. I am trying to add an image to a tab in a tabbarcontroller but nothing is getting changed.Any other alternative? – Pradeep Reddy Kypa May 07 '12 at 15:17
-
I am not sure what you mean by "it's not working". This code is from our app where it most certainly is working?! – n13 May 27 '12 at 13:37
-
This is definitely the best way to do it, and works absolutely fine. – JosephH Jul 05 '12 at 21:02
-
works great! I think `tabBarController.tabBar.selectionIndicatorImage = [[UIImage alloc] init];` is not necessary – freestyler Aug 10 '12 at 18:28
-
@HotJard - tinting isn't working, thats the whole point of this customization. If you want tinting, and this has changed significantly in iOS 7, it's a different question. – n13 Dec 10 '13 at 04:14
This is surprisingly difficult as the UITabBar
doesn't provide access to it's selected/unselected images. It can be achieved with a private API though:
@interface UITabBar (ColorExtensions)
- (void)recolorItemsWithColor:(UIColor *)color shadowColor:(UIColor *)shadowColor shadowOffset:(CGSize)shadowOffset shadowBlur:(CGFloat)shadowBlur;
@end
@interface UITabBarItem (Private)
@property(retain, nonatomic) UIImage *selectedImage;
- (void)_updateView;
@end
@implementation UITabBar (ColorExtensions)
- (void)recolorItemsWithColor:(UIColor *)color shadowColor:(UIColor *)shadowColor shadowOffset:(CGSize)shadowOffset shadowBlur:(CGFloat)shadowBlur
{
CGColorRef cgColor = [color CGColor];
CGColorRef cgShadowColor = [shadowColor CGColor];
for (UITabBarItem *item in [self items])
if ([item respondsToSelector:@selector(selectedImage)] &&
[item respondsToSelector:@selector(setSelectedImage:)] &&
[item respondsToSelector:@selector(_updateView)])
{
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [[item selectedImage] size];
// Retrieve source image and begin image context
UIImage *itemImage = [item image];
CGSize itemImageSize = [itemImage size];
CGPoint itemImagePosition;
itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) / 2);
UIGraphicsBeginImageContext(contextRect.size);
CGContextRef c = UIGraphicsGetCurrentContext();
// Setup shadow
CGContextSetShadowWithColor(c, shadowOffset, shadowBlur, cgShadowColor);
// Setup transparency layer and clip to mask
CGContextBeginTransparencyLayer(c, NULL);
CGContextScaleCTM(c, 1.0, -1.0);
CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [itemImage CGImage]);
// Fill and end the transparency layer
CGContextSetFillColorWithColor(c, cgColor);
contextRect.size.height = -contextRect.size.height;
CGContextFillRect(c, contextRect);
CGContextEndTransparencyLayer(c);
// Set selected image and end context
[item setSelectedImage:UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
// Update the view
[item _updateView];
}
}
@end
One can even create some pretty cool effects:
(source: booleanmagic.com)
It is very possible that Apple will reject an application for doing this. If the private API is removed in a future OS update, -[UITabBar recolorItemsWithColor:shadowColor:shadowOffset:shadowBlur:]
will do nothing instead of crashing.

- 21,988
- 13
- 81
- 109

- 32,196
- 6
- 66
- 89
-
This was a good suggestion, but I chose a less complicated approach. I subclassed UIToolBar, which allowed it to adapt the functionality of a UITabBar without its control over the look and feel (UIToolBar supports custom views). – obsoleteModel81 Sep 01 '09 at 08:29
-
1Can anybody show me how I can implement this code in a new "Tab Bar application" project? – Sindre Sorhus Sep 27 '09 at 17:46
-
1mofie: Add the code above to your appdelegate, then add this call to applicationDidFinishLaunching: [[tabBarController tabBar] recolorItemsWithColor:[UIColor whiteColor] shadowColor:[UIColor blackColor] shadowOffset:CGSizeMake(0.0f, -1.0f) shadowBlur:3.0f]; – rpetrich Oct 06 '09 at 21:31
-
-
how did you get the gradient in icons? When I set a color it I just plain. – Sindre Sorhus Dec 20 '09 at 23:55
-
-
1My app got rejected because of "_updateView". Is there a way to do this without it? – Sindre Sorhus Dec 29 '09 at 02:09
-
-
How would I use "[UIColor colorWithPatternImage:]" to get the blue gloss effect like the original, only with a different color? – Sindre Sorhus Dec 30 '09 at 21:46
-
5@jkp: clearly labeled as such. people can make their own decisions. not everyone develops for the App Store – rpetrich May 24 '10 at 01:52
-
@rpetrich - what do you think about my answer listed here ? Requesting you to go through it once. – sagarkothari Sep 21 '11 at 14:41
-
@sugar: Seems like it works. Doesn't really look like an `UITabBar` though. – rpetrich Sep 29 '11 at 00:43
-
This doesn't work with Retina graphics. On iPhone 4 with iOS 5 it shows pixelated graphics. – neoneye Nov 21 '11 at 09:58
-
5Note that `UITabBarItem` on iOS 5 has **public API** to allow you to fully customise the buttons. Use `- (void)setFinishedSelectedImage:(UIImage *)selectedImage withFinishedUnselectedImage:(UIImage *)unselectedImage`. Use in conjunction with `UITabBar` properties `backgroundImage` and `selectionIndicatorImage` – Joshua J. McKinnon Jun 15 '12 at 00:22
Adding gradient is very simple, add the following lines of code:
CGFloat components[8] = {0.0,0.4,1.0,0.2,0.0,0.6,1.0,1.0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, NULL, 2);
CGContextDrawLinearGradient(cxt, colorGradient,CGPointZero,CGPointMake(0,contextRect.size.height),0);
This will get you very close to what Apple does on the tabbar but, not exact. To get there, just add two more points/colors in components and instead of NULL
in CGGradientCreateWithColorComponents
, use something like {0,0.5,0.6,1.0}
. In fact, all you need is one background color and three alpha points (with color part being all 1s, since you just need shading while retaining a single color profile).
I will post my code if this isn't clear ... cheers.

- 2,234
- 1
- 21
- 18
It's been almost a year but here is the code. Add this as a category to UIImage or convert to class-wide. Remember, the image you are passing (self) has to be an alpha only image (the mask is created based on the visible parts of the image).
- (UIImage *) imageWithBackgroundColor:(UIColor *)bgColor
shadeAlpha1:(CGFloat)alpha1
shadeAlpha2:(CGFloat)alpha2
shadeAlpha3:(CGFloat)alpha3
shadowColor:(UIColor *)shadowColor
shadowOffset:(CGSize)shadowOffset
shadowBlur:(CGFloat)shadowBlur {
UIImage *image = self;
CGColorRef cgColor = [bgColor CGColor];
CGColorRef cgShadowColor = [shadowColor CGColor];
CGFloat components[16] = {1,1,1,alpha1,1,1,1,alpha1,1,1,1,alpha2,1,1,1,alpha3};
CGFloat locations[4] = {0,0.5,0.6,1};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, (size_t)4);
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [image size];
//contextRect.size = CGSizeMake([image size].width+5,[image size].height+5);
// Retrieve source image and begin image context
UIImage *itemImage = image;
CGSize itemImageSize = [itemImage size];
CGPoint itemImagePosition;
itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) / 2);
UIGraphicsBeginImageContext(contextRect.size);
CGContextRef c = UIGraphicsGetCurrentContext();
// Setup shadow
CGContextSetShadowWithColor(c, shadowOffset, shadowBlur, cgShadowColor);
// Setup transparency layer and clip to mask
CGContextBeginTransparencyLayer(c, NULL);
CGContextScaleCTM(c, 1.0, -1.0);
CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [itemImage CGImage]);
// Fill and end the transparency layer
CGContextSetFillColorWithColor(c, cgColor);
contextRect.size.height = -contextRect.size.height;
CGContextFillRect(c, contextRect);
CGContextDrawLinearGradient(c, colorGradient,CGPointZero,CGPointMake(contextRect.size.width*1.0/4.0,contextRect.size.height),0);
CGContextEndTransparencyLayer(c);
//CGPointMake(contextRect.size.width*3.0/4.0, 0)
// Set selected image and end context
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGColorSpaceRelease(colorSpace);
CGGradientRelease(colorGradient);
return resultImage;
}
For example, the following will produce an effect very similar to what the native tabbar does:
UIImage *niceImage = [[UIImage imageNamed:@"image_name"] imageWithBackgroundColor:[UIColor colorWithRed:41.0/255.0 green:147.0/255.0 blue:239.0/255.0 alpha:1.0]
shadeAlpha1:0.6
shadeAlpha2:0.0
shadeAlpha3:0.4
shadowColor:[UIColor blackColor]
shadowOffset:CGSizeMake(0.0f, -1.0f)
shadowBlur:3.0];

- 2,234
- 1
- 21
- 18
-
This really does create similar effect as TabBarItem's selected image. It's close, but not perfect. Thank you very much! – Palimondo Mar 02 '11 at 18:15
-
-
1@Moshe - To return an image of the same resolution as the original, replace the `UIGraphicsBeginImageContext(contextRect.size)` call with `UIGraphicsBeginImageContextWithOptions(contextRect.size, NO, self.scale)`. Keep in mind that this function is only available in iOS 4.0 and later. – Ryan Grimm Apr 27 '12 at 16:57
There is a solution to this using a custom implemented tab bar at the iDev Recipes site.
http://idevrecipes.com/2011/01/04/how-does-the-twitter-iphone-app-implement-a-custom-tab-bar

- 2,193
- 2
- 14
- 15
I asked a question on how to color the "offstate" of a button. Someone gave me a solution that also had the bonus of removing the gradient. here's the quesiton and his answer:
Q: iphone - tabbar set imagetintcolor (offstate)
A: Take a look at the "Managing the Finished and Selected Image" task's section of the docs of UITabBarItem.
Use Following images ( Assuming, tabBar is having 5 Tabs as follows )
Create a new project using - "TabBar Application" template & Place following code.
Contents of AppDel.h File.
#import <UIKit/UIKit.h>
@interface cTabBarAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
@property (nonatomic, retain) IBOutlet UIImageView *imgV;
@end
Contents of AppDel.m File.
#import "cTabBarAppDelegate.h"
@implementation cTabBarAppDelegate
@synthesize window=_window;
@synthesize tabBarController=_tabBarController;
@synthesize imgV = _imgV;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.tabBarController.delegate=self;
self.imgV.frame=CGRectMake(0, 425, 320, 55);
[self.tabBarController.view addSubview:self.imgV];
self.tabBarController.selectedIndex=0;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
NSUInteger index=[[tabBarController viewControllers] indexOfObject:viewController];
switch (index) {
case 0:
self.imgV.image=[UIImage imageNamed:@"tBar1.png"];
break;
case 1:
self.imgV.image=[UIImage imageNamed:@"tBar2.png"];
break;
case 2:
self.imgV.image=[UIImage imageNamed:@"tBar3.png"];
break;
case 3:
self.imgV.image=[UIImage imageNamed:@"tBar4.png"];
break;
case 4:
self.imgV.image=[UIImage imageNamed:@"tBar5.png"];
break;
default:
break;
}
return YES;
}

- 915
- 1
- 12
- 20

- 24,520
- 50
- 165
- 235