60

How can I change inactive icon/text color on iOS 7 tab bar? The one in gray color.

enter image description here

Gabriel.Massana
  • 7,917
  • 6
  • 56
  • 79
Pablo
  • 24,270
  • 32
  • 112
  • 196
  • Possible duplicate of [Change tab bar item selected color in a storyboard](http://stackoverflow.com/questions/26835148/change-tab-bar-item-selected-color-in-a-storyboard) – Marcelo Gracietti Jan 01 '17 at 23:26
  • 1
    @Marcelo Gracietti. Please check the dates first. This is not duplicate, the one you mentioned is. – Pablo Jan 05 '17 at 11:10

19 Answers19

116

You can also set the property Render As of your tab bar images within your asset catalog directly. There you have the option to set the property to Default, Original Image and Template Image.

Set render option of image

anka
  • 3,639
  • 1
  • 26
  • 35
  • I like the solution, but there seems to be a bug in iOS 8: I use an original image für normal state and a template image for selected state. The normal image works, but the selected image don't appear. Anyone else experienced that? – Hans One Aug 05 '15 at 08:53
  • @HansOne Probably you didn't select "Selected Image" property in Tab Bar Item, only selected "Image" property. – Thomás Pereira Oct 21 '15 at 13:26
  • the text under the image is still grey – user3722523 Nov 29 '15 at 18:50
91

In every first ViewController for each TabBar:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // changing the unselected image color, you should change the selected image 
    // color if you want them to be different
    self.tabBarItem.selectedImage = [[UIImage imageNamed:@"yourImage_selectedImage"]
    imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

    self.tabBarItem.image = [[UIImage imageNamed:@"yourImage_image"] 
    imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}

The clue of this code is 'UIImageRenderingModeAlwaysOriginal':

Rendering Modes by Apple Documentation:

UIImageRenderingModeAutomatic,          // Use the default rendering mode for the context where the image is used    
UIImageRenderingModeAlwaysOriginal,     // Always draw the original image, without treating it as a template
UIImageRenderingModeAlwaysTemplate,     // Always draw the image as a template image, ignoring its color information

To change text color:

In AppDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Add this if you only want to change Selected Image color 
    // and/or selected image text
    [[UITabBar appearance] setTintColor:[UIColor redColor]];

    // Add this code to change StateNormal text Color,
    [UITabBarItem.appearance setTitleTextAttributes:
    @{NSForegroundColorAttributeName : [UIColor greenColor]} 
    forState:UIControlStateNormal];

    // then if StateSelected should be different, you should add this code
    [UITabBarItem.appearance setTitleTextAttributes:
    @{NSForegroundColorAttributeName : [UIColor purpleColor]} 
    forState:UIControlStateSelected];

    return YES;
}
Gabriel.Massana
  • 7,917
  • 6
  • 56
  • 79
  • 5
    Setting tabBarItem in every `viewController` is bad idea, because they will not be necessarily instantiated at once. But even after that, on iOS 7, existing image simply disappears. Debugger shows images are properly loaded. They have alpha transparency. – Pablo Mar 31 '14 at 17:01
  • 2
    I mean, in every first ViewController for every TabBar. – Gabriel.Massana Mar 31 '14 at 17:14
  • images are disappeared, like I said. – Pablo Mar 31 '14 at 17:31
  • The hierarchy of Favorites, Recents, Books in your app are embeded in a Navigation Controller? If yes, a test in my Simulator is working without problem. If not is disappearing the whole TabBar – Gabriel.Massana Mar 31 '14 at 18:37
  • No, I don't have Navigation Controller at all. – Pablo Mar 31 '14 at 18:40
  • When are the images disappearing? When you click where? Wasn't disappearing with my snippet? – Gabriel.Massana Mar 31 '14 at 19:15
  • right after application appears. Without snippet they were set from storyboard and all visible. – Pablo Mar 31 '14 at 19:17
  • Weird. Do you have images named `yourImage_selectedImage` and `yourImage_image` in your project? Or images who fit with `imageNamed:`? – Gabriel.Massana Mar 31 '14 at 19:19
  • yes, checked with debugger, if not valid then object is nil. – Pablo Mar 31 '14 at 19:22
  • png. I think Apple is enforcing to use gray color as inactive icon color. – Pablo Mar 31 '14 at 20:28
  • If you could share demo that would be great to compare what might be different. – Pablo Mar 31 '14 at 20:59
  • @Pablo is the problem solved? I set tab bar item in each view controller and the icon disappeared as well. I am using iOS8. – yehe Jul 25 '15 at 00:27
  • What if I have 2 tab bars with different appearances (different text colors)? Seems like this method sucks. – vahotm Nov 17 '17 at 13:48
14

for changing color of unselect icons of tabbar

For below iOS 10:

// this code need to be placed on home page of tabbar    
for(UITabBarItem *item in self.tabBarController.tabBar.items) {
    item.image = [item.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}

Above iOS 10:

// this need to be in appdelegate didFinishLaunchingWithOptions
[[UITabBar appearance] setUnselectedItemTintColor:[UIColor blackColor]];
Vaibhav Gaikwad
  • 306
  • 5
  • 12
  • 1
    If you don't have to support below iOS 10, this is the best answer. – CBanga Jun 20 '17 at 15:23
  • Agree with CBanga. This is the best answer - one function to cover all tabbar View Controllers. It also removes the issue of waiting for the viewDidLoad methods to run in each tabbar View Controller. Nice one. – Peza Dec 13 '17 at 09:42
  • This line: [[UITabBar appearance] setUnselectedItemTintColor:[UIColor blackColor]] is not working in iOS 13! – Arash HF Jul 29 '20 at 20:22
10

Instead adding it to every UIViewController, you can create an extension and alter the appearance of an UITabBarController

Change unselected icon color

extension UITabBarController {
    override public func viewDidLoad() {
        super.viewDidLoad()

        tabBar.items?.forEach({ (item) -> () in
           item.image = item.selectedImage?.imageWithColor(UIColor.redColor()).imageWithRenderingMode(.AlwaysOriginal)
        })
    }
}

Change selected icon color

let tabBarAppearance = UITabBar.appearance()
tabBarAppearance.tintColor = UIColor.blackColor()

Change (un)selected title color

let tabBarItemApperance = UITabBarItem.appearance()
tabBarItemApperance.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Edmondsans-Bold", size: 10)!, NSForegroundColorAttributeName:UIColor.redColor()], forState: UIControlState.Normal)
tabBarItemApperance.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Edmondsans-Bold", size: 10)!, NSForegroundColorAttributeName:UIColor.blackColor()], forState: UIControlState.Selected)

UIImage extension

extension UIImage {
    func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext()
        CGContextTranslateCTM(context!, 0, self.size.height)
        CGContextScaleCTM(context!, 1.0, -1.0);
        CGContextSetBlendMode(context!, .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
    }
}
Steve Stomp
  • 278
  • 4
  • 12
7

There is a better way without using each ViewController by only using appdelegate.m

In your AppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions function, try this.

UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
UITabBar *tabBar = tabBarController.tabBar;

// repeat for every tab, but increment the index each time
UITabBarItem *firstTab = [tabBar.items objectAtIndex:0];

// also repeat for every tab
firstTab.image = [[UIImage imageNamed:@"someImage.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal ];
firstTab.selectedImage = [[UIImage imageNamed:@"someImageSelected.png"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
Umit Kaya
  • 4,719
  • 2
  • 34
  • 46
7

To change tab selection color instead blue color:

  1. Select the tabItem.
  2. From "Show the Identity inspector" in the right side menu.
  3. Set "tintColor" attribute with your prefer color.

enter image description here

Ahmed Lotfy
  • 3,326
  • 22
  • 26
4

The new answer to do this programmatically as of iOS 10+ with Swift 3 is to use the unselectedItemTintColor API. For example, if you have initialized your tab bar controller inside your AppDelegate, it would looks like the following:

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        ...

        let firstViewController = VC1()
        let secondViewController = VC2()
        let thirdViewController = VC3()


        let tabBarCtrl = UITabBarController()
        tabBarCtrl.viewControllers = [firstViewController, secondViewController, thirdViewController]

        // set the color of the active tab
        tabBarCtrl.tabBar.tintColor = UIColor.white

        // set the color of the inactive tabs
        tabBarCtrl.tabBar.unselectedItemTintColor = UIColor.gray

        // set the text color

        ...
    }

And for setting the selected and unselected text colors:

let unselectedItem = [NSForegroundColorAttributeName: UIColor.green]
let selectedItem = [NSForegroundColorAttributeName: UIColor.red]

self.tabBarItem.setTitleTextAttributes(unselectedItem, for: .normal)
self.tabBarItem.setTitleTextAttributes(selectedItem, for: .selected)
Anchor
  • 1,166
  • 15
  • 23
3

In Swift 3.0 you can write it as follows

For unselected tab bar image

viewController.tabBarItem.image = UIImage(named: "image")?.withRenderingMode(.alwaysOriginal)

For selected tab bar image

viewController.tabBarItem.selectedImage = UIImage(named: "image")?.withRenderingMode(.alwaysOriginal)
kbokdia
  • 399
  • 3
  • 11
3

Instead of adding rendering image code in each viewController for tabBarItem, use extension

extension UITabBar{
     func inActiveTintColor() {
        if let items = items{
            for item in items{
                item.image =  item.image?.withRenderingMode(.alwaysOriginal)
                item.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.green], for: .normal)
                item.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.white], for: .selected)
            }
        }
    }
}

Then call this in your UITabBarController class like

class CustomTabBarViewController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tabBar.inActiveTintColor()
    }
}

You will get output like : enter image description here NOTE: Don't forget to assign CustomTabBarViewController class to your TabBarController in storyboard.

Preeti Rani
  • 595
  • 4
  • 17
3

I think it's time to use

UITabBar unselectedItemTintColor appearance

/// Unselected items in this tab bar will be tinted with this color. Setting this value to nil indicates that UITabBar should use its default value instead.
    @available(iOS 10.0, *)
    @NSCopying open var unselectedItemTintColor: UIColor?

Just add this line into App did finish launching

UITabBar.appearance().unselectedItemTintColor = {your color}
// Example
UITabBar.appearance().unselectedItemTintColor = .black

Tab Bar unselectedItemTintColor appearance

LLIAJLbHOu
  • 1,225
  • 11
  • 16
2

I think @anka's answer is quite good, and I also added the following code to enable tint color for highlighted items:

    let image = UIImage(named:"tab-account")!.imageWithRenderingMode(.AlwaysTemplate)
    let item = tabBar.items![IC.const.tab_account] as! UITabBarItem
    item.selectedImage = image

Or in one line:

    (tabBar.items![IC.const.tab_account] as! UITabBarItem).selectedImage = UIImage(named:"tab-account")!.imageWithRenderingMode(.AlwaysTemplate)

So it looks like:

tabbar

superarts.org
  • 6,508
  • 1
  • 53
  • 43
2

You only need put this code in your first ViewController called for TabBarViewController (ViewDidload):

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self loadIconsTabBar];
}

-(void) loadIconsTabBar{
        UITabBar *tabBar = self.tabBarController.tabBar;
        //
        UITabBarItem *firstTab = [tabBar.items objectAtIndex:0];
        UITabBarItem *secondTab = [tabBar.items objectAtIndex:1];
        firstTab.image = [[UIImage imageNamed:@"icono1.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal ];
        firstTab.selectedImage = [[UIImage imageNamed:@"icono1.png"]imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        secondTab.image = [[UIImage imageNamed:@"icono2.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal ];
        secondTab.selectedImage = [[UIImage imageNamed:@"icono2.png"]imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    }
Jose Pose S
  • 856
  • 10
  • 30
1

You only need put this code in your appDelegate.m called (didFinishLaunchingWithOptions):

[UITabBarItem.appearance setTitleTextAttributes:
@{NSForegroundColorAttributeName : [UIColor whiteColor]}
                                       forState:UIControlStateNormal];


[UITabBarItem.appearance setTitleTextAttributes:
@{NSForegroundColorAttributeName : [UIColor orangeColor]}
                                       forState:UIControlStateSelected];

[[UITabBar appearance] setTintColor:[UIColor whiteColor]]; // for unselected items that are gray
[[UITabBar appearance] setUnselectedItemTintColor:[UIColor whiteColor]]; 
Amit Garg
  • 34
  • 5
1

If you are looking for an iOS 11 swift 4 solution, do something like this in the appDelegate. This is changing all the unselected ones to black.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    UITabBar.appearance().unselectedItemTintColor = UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 1)

    return true
}
Mohammad Usman
  • 30,882
  • 16
  • 80
  • 78
thalacker
  • 878
  • 11
  • 30
0

The best way to change the color of the Selected tab bar item is add a single code on appdelegate didFinishLaunchingWithOptions method

UITabBar.appearance().tintColor = UIColor(red: 242/255.0, green: 32/255.0, blue: 80/255.0, alpha: 1.0)

It will change the selected item text color

Sandu
  • 409
  • 4
  • 8
0

You can do it all through the interface builder, check this answer out, it shows how to do both active and inactive, "Change tab bar item selected color in a storyboard"

Community
  • 1
  • 1
Maria
  • 4,139
  • 1
  • 23
  • 23
0

for swift 3:

    // both have to declare in view hierarchy method
    //(i.e: viewdidload, viewwillappear) according to your need.

    //this one is, when tab bar is selected
    self.tabBarItem.selectedImage = UIImage.init(named: "iOS")?.withRenderingMode(.alwaysOriginal)

    // this one is when tab bar is not selected
    self.tabBarItem.image = UIImage.init(named: "otp")?.withRenderingMode(.alwaysOriginal)
Tanvir Nayem
  • 654
  • 8
  • 23
-1

this worked for me SWIFT 3

viewConroller.tabBarItem = UITabBarItem(title: "", image: UIImage(named: "image")?.withRenderingMode(.alwaysOriginal),
                                selectedImage:  UIImage(named: "image"))
devzaid
  • 35
  • 1
  • 13
-3

Swift solution : for UNSELECED item : in every ViewController -> ViewDidLoad()

self.tabBarItem = UITabBarItem(title: nil, image: UIImage(named: "PHOTO_NAME")?.imageWithRenderingMode(.AlwaysOriginal), selectedImage: UIImage(named: "NAME"))
Ben Siso
  • 5
  • 2