UITabBarItem Tab Bar Item Individual Selected Background Color

11,079

Solution 1

how can I change the selected background color for individual tab bar items

Tab bar items do not have a "selected background color". What they have, which you can set, is a selectedImage. By setting this to an image whose rendering mode is .AlwaysOriginal, you can dictate the look of the entire tab bar item image when it is selected, as opposed to when it is not selected.

Solution 2

Add this to application:didFinishLaunchingWithOptions:

UIColor *backgroundColor = [UIColor greenColor];

// set the bar background color
[[UITabBar appearance] setBackgroundImage:[AppDelegate imageFromColor:backgroundColor forSize:CGSizeMake(320, 49) withCornerRadius:0]];

// set the text color for selected state
[[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], UITextAttributeTextColor, nil] forState:UIControlStateSelected];
// set the text color for unselected state
[[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], UITextAttributeTextColor, nil] forState:UIControlStateNormal];

// set the selected icon color
[[UITabBar appearance] setTintColor:[UIColor whiteColor]];
[[UITabBar appearance] setSelectedImageTintColor:[UIColor whiteColor]];
// remove the shadow
[[UITabBar appearance] setShadowImage:nil];

// Set the dark color to selected tab (the dimmed background)
[[UITabBar appearance] setSelectionIndicatorImage:[AppDelegate imageFromColor:[UIColor colorWithRed:26/255.0 green:163/255.0 blue:133/255.0 alpha:1] forSize:CGSizeMake(64, 49) withCornerRadius:0]];

add a helper function to turn UIColor into UIImage

You may put this code to AppDelegate or anywhere else:

+ (UIImage *)imageFromColor:(UIColor *)color forSize:(CGSize)size withCornerRadius:(CGFloat)radius
{
    CGRect rect = CGRectMake(0, 0, size.width, size.height);
    UIGraphicsBeginImageContext(rect.size);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // Begin a new image that will be the new image with the rounded corners
    // (here with the size of an UIImageView)
    UIGraphicsBeginImageContext(size);

    // Add a clip before drawing anything, in the shape of an rounded rect
    [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius] addClip];
    // Draw your image
    [image drawInRect:rect];

    // Get the image, here setting the UIImageView image
    image = UIGraphicsGetImageFromCurrentImageContext();

    // Lets forget about that we were drawing
    UIGraphicsEndImageContext();

    return image;
}

Solution 3

I found workaround without adding additional images

class TabBarController: UITabBarController {
override func viewDidLoad() {
    super.viewDidLoad()
    // update first item
    dispatch_async(dispatch_get_main_queue()) {
        self.setSelection(self.tabBar.selectedItem!)
    }
}

// MARK: - UITabBarDelegate handlers

override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
    clearSelections()
    setSelection(item)
}

// MARK: - Selection Methods

func setSelection(item:UITabBarItem) {
    dispatch_async(dispatch_get_main_queue()) {
        for i in 0..<self.tabBar.items!.count {
            let ii = self.tabBar.items![i]
            if(item == ii) {
                let sv = self.tabBar.subviews[i+1]
                let label:UILabel =  sv.subviews[1] as! UILabel
                print("didSelectItem \(label.text) = \(ii.title)")
                sv.backgroundColor = UIColor() // Selection color
            }
        }
    }
}

func clearSelections() {
    for s in tabBar.subviews {
        s.backgroundColor = UIColor.clearColor()
    }
}
}

In result I can set background color of selected tab enter image description here

Share:
11,079
exotue
Author by

exotue

Updated on June 30, 2022

Comments

  • exotue
    exotue almost 2 years

    In my project, I am using an extension of UIImage to create change the selected background color of the tab bar items:

    extension UIImage {
    func imageWithColor(tintColor: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    
        let context = UIGraphicsGetCurrentContext() as CGContextRef!
        CGContextTranslateCTM(context, 0, self.size.height)
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, CGBlendMode.Normal)
    
        let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect
        CGContextClipToMask(context, rect, self.CGImage)
        tintColor.setFill()
        CGContextFillRect(context, rect)
    
        let newImage = UIGraphicsGetImageFromCurrentImageContext() as UIImage
        UIGraphicsEndImageContext()
    
        return newImage
    }
    
    func makeImageWithColorAndSize(color: UIColor, size: CGSize) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        color.setFill()
        UIRectFill(CGRectMake(0, 0, 100, 100))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }   
    }
    

    And then using that in my MainTabBarController

     class MainTabBarController: UITabBarController {
     override func viewDidLoad() {
        super.viewDidLoad()
    
        let itemIndex = 0
        let bgColor = UIColor(red: 194/255.0, green: 39/255.0, blue: 65/255.0, alpha: 1.0)
    
        let itemWidth = tabBar.frame.width / CGFloat(tabBar.items!.count)
        let frame = CGRectMake(CGFloat(itemWidth) * CGFloat(itemIndex), 0, itemWidth, tabBar.frame.height)
        let bgView = UIView(frame: frame)
    
        bgView.backgroundColor = bgColor
        tabBar.insertSubview(bgView, atIndex: 0)
    
        for item in self.tabBar.items as [UITabBarItem]! {
            if let image = item.image {
                item.image = image.imageWithColor(UIColor.whiteColor()).imageWithRenderingMode(.AlwaysOriginal)
            }
    
    
            // Sets the default color of the icon of the selected UITabBarItem and Title
            UITabBar.appearance().tintColor = UIColor.whiteColor()
    
            // Sets the default color of the background of the UITabBar
            UITabBar.appearance().barTintColor = UIColor(red: 39/255.0, green: 39/255.0, blue: 39/255.0, alpha: 1.0)
    
            // 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)
    
    
            print(UITabBar.appearance().selectionIndicatorImage)
    
    
    
            UITabBar.appearance().selectionIndicatorImage = UIImage().makeImageWithColorAndSize(UIColor(red: 21/255.0, green: 21/255.0, blue: 21/255.0, alpha: 1.0), size: CGSizeMake(tabBar.frame.width/4, tabBar.frame.height))
    
        }
    
        // Do any additional setup after loading the view.
    }
    

    This works, but how can I change the selected background color for individual tab bar items?