IOS 8 Tab Bar Item Background Colour

I've been trying to find the solution to this for the last week, and I have had no luck after trying every possible solution I could find or think of. Every solution I found and have attempted has either not worked, or been outdated.

I have 5 UITabBarItem's in a UITabBar placed within UITabBarController. I want to change the background color of the UITabBarItem when it is selected, and of course have it change back when the selected item changes.

I am using Swift, and iOS SDK 8.3 in Xcode 6.3.1. If you can only answer in Objective-C that is fine too, any answer will help! Thank you all in advance, I really appreciate it!

EDIT: Here is a visual example of what I would want it to do.

Different Background Color


Solution 1:

In your tabBarController, you can set the default UITabBar tintColor, barTintColor, selectionIndicatorImage (cheating a bit here) and renderingMode of the images, see comments below:

    class MyTabBarController: UITabBarController, UINavigationControllerDelegate {
      ...
      override func viewDidLoad() {
        ...
        // Sets the default color of the icon of the selected UITabBarItem and Title
        UITabBar.appearance().tintColor = UIColor.redColor()

        // Sets the default color of the background of the UITabBar
        UITabBar.appearance().barTintColor = UIColor.blackColor()

        // Sets the background color of the selected UITabBarItem (using and plain colored UIImage with the width = 1/5 of the tabBar (if you have 5 items) and the height of the tabBar)
        UITabBar.appearance().selectionIndicatorImage = UIImage().makeImageWithColorAndSize(UIColor.blueColor(), size: CGSizeMake(tabBar.frame.width/5, tabBar.frame.height))

        // Uses the original colors for your images, so they aren't not rendered as grey automatically.
        for item in self.tabBar.items as! [UITabBarItem] {
          if let image = item.image {
            item.image = image.imageWithRenderingMode(.AlwaysOriginal)
          }
        }
      }
      ...
    }

And you will want to extend the UIImage class to make the plain colored image with the size you need:

extension UIImage {
  func makeImageWithColorAndSize(color: UIColor, size: CGSize) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    color.setFill()
    UIRectFill(CGRectMake(0, 0, size.width, size.height))
    var image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
  }
}

Solution 2:

You can try this one. Add this in AppDelegate.swift.

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

        UITabBar.appearance().translucent = false
        UITabBar.appearance().barTintColor = UIColor(rgba: "#12296f")
        UITabBar.appearance().tintColor = UIColor.whiteColor()

        return true
    }

Don't forget to include this library. https://github.com/yeahdongcn/UIColor-Hex-Swift

Solution 3:

Inspired by Gwendle, this is how I've solved it:

override func viewWillAppear(animated: Bool) {
    guard let tabBar = tabBarController?.tabBar else { return }
    tabBar.tintColor = UIColor.whiteColor()
    tabBar.selectionIndicatorImage = UIImage().makeImageWithColorAndSize(UIColor.redColor(), size: CGSizeMake(tabBar.frame.width/5, tabBar.frame.height))
    super.viewWillAppear(animated)
}

And also used the extension:

extension UIImage {
    func makeImageWithColorAndSize(color: UIColor, size: CGSize) -> UIImage {
        UIGraphicsBeginImageContext(size)
        color.setFill()
        UIRectFill(CGRectMake(0, 0, size.width, size.height))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
}

Keep in mind that after you set the selectionIndicationImage it remains set for all your other tabs. Here's an example how to remove it, by setting it to nil in every other view controller in the remaining tabs:

override func viewWillAppear(animated: Bool) {
    tabBarController?.tabBar.tintColor = UIColor.redColor()
    tabBarController?.tabBar.selectionIndicatorImage = nil
    super.viewWillAppear(animated)
}

Implemented using Swift 2.