Question

Can I change the background color of a specific UITabBarItem in a UITabBar?

I know how to change all the background of the selected background, using:

[[UITabBar appearance] setBarTintColor:[UIColor redColor]];
[[UITabBar appearance] setTintColor:[UIColor blueColor]];
[[UITabBar appearance] setSelectedImageTintColor:[UIColor yellowColor]];

But can it be done for only one item without subclassing?

Thanks

Was it helpful?

Solution

You can add a subview to the parent tabBar, and set a background color on the subview. You can use the tabBar frame dimensions to calculate the offset and width of your tabBarItem, and then insert the subview underneath.

Example (in Swift):

// Add background color to middle tabBarItem
let itemIndex = 2
let bgColor = UIColor(red: 0.08, green: 0.726, blue: 0.702, alpha: 1.0)

let itemWidth = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgView = UIView(frame: CGRectMake(itemWidth * itemIndex, 0, itemWidth, tabBar.frame.height))
bgView.backgroundColor = bgColor
tabBar.insertSubview(bgView, atIndex: 0)

OTHER TIPS

in Swift: This solution is for apps using Auto Layout . Main difference between other solution is that: tabBar.frame.width is not getting actual device's screen width. So, bgView is appearing wrong place.

You can fix it with this : UIScreen.main.bounds.width

let tabWidth: CGFloat = UIScreen.main.bounds.width / CGFloat(self.tabbar!.items!.count)
let tabIndex: CGFloat = 2
let bgColor: UIColor = .redColor
let bgView = UIView(frame: CGRectMake(tabWidth * tabIndex, 0, tabWidth, 49))
bgView.backgroundColor = bgColor
self.tabbar!.insertSubview(bgView, atIndex: 0)

49 is a default height of UITabbar

Objective C solution:

int itemIndex = 3;
UIColor* bgColor = [UIColor colorWithRed:(245/255.f) green:(192/255.f) blue:(47/255.f) alpha:1];

float itemWidth = self.tabBarController.tabBar.frame.size.width / 5.0f; //5 = tab bar items
UIView* bgView = [[UIView alloc]initWithFrame: CGRectMake(itemWidth*itemIndex, 0,itemWidth, self.tabBarController.tabBar.frame.size.height)];
bgView.backgroundColor = bgColor;
[self.tabBarController.tabBar insertSubview:bgView atIndex:1];

Updated for Swift 4:

let itemIndex: CGFloat = 2.0
let bgColor = UIColor.ownBlue

let itemWidth = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgView = UIView(frame: CGRect(x: itemWidth * itemIndex, y: 0, width: itemWidth, height: tabBar.frame.height))

bgView.backgroundColor = bgColor
tabBar.insertSubview(bgView, at: 0)

You cannot really do this with the tint color property. See this post about the fact that even the setSelectedImageTintColor does not really seem to be working (it did not last time I checked).

The solution is to change the tintColor on the fly for the item in question. You can do this ad hoc whenever the selected item changes by implementing the UITabBarDelegate method tabBar:didSelectItem: e.g. in the app delegate.

Late to the game, but this is how I did it. I made the tabs look like buttons, with rounded views. The answers above, have issues when the device is rotated, or the app is sent into a split window.

This solution marries the background directly to each tab, using auto-layout, so they naturally follow the tab bar changes.

This is done on the custom subclass of UITabBarController.

First, I set the colors (white for unselected, and black for selected), of the icons in the tab items, then, I iterate the tabs, and insert backgrounds to each, using auto layout to have them cleave to the tabs:

override func viewDidLoad() {
    super.viewDidLoad()
    let appearance = UITabBarAppearance()
    appearance.stackedLayoutAppearance.normal.iconColor = .white
    appearance.stackedLayoutAppearance.selected.iconColor = .black
    appearance.inlineLayoutAppearance.normal.iconColor = .white
    appearance.inlineLayoutAppearance.selected.iconColor = .black
    appearance.compactInlineLayoutAppearance.normal.iconColor = .white
    appearance.compactInlineLayoutAppearance.selected.iconColor = .black

    tabBar.subviews.forEach {
        if let item = $0 as? UIControl {
            let wrapper = UIView()
            wrapper.isUserInteractionEnabled = false
            wrapper.clipsToBounds = true
            wrapper.backgroundColor = tabBar.tintColor
            wrapper.layer.cornerRadius = 8
            item.insertSubview(wrapper, at: 0)
            wrapper.translatesAutoresizingMaskIntoConstraints = false
            wrapper.leadingAnchor.constraint(equalTo: item.leadingAnchor).isActive = true
            wrapper.trailingAnchor.constraint(equalTo: item.trailingAnchor).isActive = true
            wrapper.topAnchor.constraint(equalTo: item.topAnchor).isActive = true
            wrapper.bottomAnchor.constraint(equalTo: item.bottomAnchor).isActive = true
        }
    }
}

The reason this works, is that the tab bar implements the tab items as an internal subclass of UIControl, which is a UIView.

I can add views underneath the control.

This ends up looking like this:

Sample Tab Bar

NB: Turning off user interaction is important, as is inserting at 0.

The drawback is that there's no way to tell which item is the selected one (at the time the background images are created).

ALSO NB: Apple REALLY doesn't want us mucking about in the tab bar, so I could see this method (as well as the ones above), breaking in some future OS upgrade.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top