Is it possible to change UITabBarItem badge color

前端 未结 14 1487
别那么骄傲
别那么骄傲 2020-12-05 00:14

I want to change background color of UITabBarItem badge but can\'t find any resource on how to make it.

相关标签:
14条回答
  • 2020-12-05 01:05

    You need to specify tab item at index to change badge color, #available in iOS 10 ,

        if #available(iOS 10.0, *) 
        {
            self.kAppTabBarController.tabBar.items![1].badgeColor = YOUR_COLOR
        }
    
    0 讨论(0)
  • 2020-12-05 01:05
    // change TabBar BadgeView background Color
    -(void)changeTabBarBadgeViewBgColor:(UITabBar*)tabBar {
        for (UIView* tabBarButton in tabBar.subviews) {
            for (UIView* badgeView in tabBarButton.subviews) {
                NSString* className = NSStringFromClass([badgeView class]);
    
                // looking for _UIBadgeView
                if ([className rangeOfString:@"BadgeView"].location != NSNotFound) {
                    for (UIView* badgeSubview in badgeView.subviews) {
                        NSString* className = NSStringFromClass([badgeSubview class]);
    
                        // looking for _UIBadgeBackground
                        if ([className rangeOfString:@"BadgeBackground"].location != NSNotFound) {
                            @try {
                                [badgeSubview setValue:nil forKey:@"image"];
                                [badgeSubview setBackgroundColor:[UIColor blueColor]];
                                badgeSubview.clipsToBounds = YES;
                                badgeSubview.layer.cornerRadius = badgeSubview.frame.size.height/2;
                            }
                            @catch (NSException *exception) {}
                        }
    
                        if ([badgeSubview isKindOfClass:[UILabel class]]) {
                            ((UILabel *)badgeSubview).textColor = [UIColor greenColor];
                        }
                    }
                }
            }
        }
    }
    

    0 讨论(0)
  • 2020-12-05 01:06

    I wrote this piece of code for my app, but I have only tested it in iOS 7.

    for (UIView* tabBarButton in self.tabBar.subviews) {
        for (UIView* badgeView in tabBarButton.subviews) {
            NSString* className = NSStringFromClass([badgeView class]);
    
            // looking for _UIBadgeView
            if ([className rangeOfString:@"BadgeView"].location != NSNotFound) {
                for (UIView* badgeSubview in badgeView.subviews) {
                    NSString* className = NSStringFromClass([badgeSubview class]);
    
                    // looking for _UIBadgeBackground
                    if ([className rangeOfString:@"BadgeBackground"].location != NSNotFound) {
                        @try {
                            [badgeSubview setValue:[UIImage imageNamed:@"YourCustomImage.png"] forKey:@"image"];
                        }
                        @catch (NSException *exception) {}
                    }
    
                    if ([badgeSubview isKindOfClass:[UILabel class]]) {
                        ((UILabel *)badgeSubview).textColor = [UIColor greenColor];
                    }
                }
            }
        }
    }
    

    You're only able to update the badge background with an image, not a color. I have also exposed the badge label if you wanted to update that in some way.

    Its important to note that this code must be called after setting the tabBarItem.badgeValue!

    EDIT: 4/14/14

    The above code will work in iOS 7 when called anywhere. To get it working in iOS 7.1 call it in the view controllers -viewWillLayoutSubviews.

    EDIT: 12/22/14

    Here's an updated snippet which I'm currently using. I put the code in a category extension for simplicity.

    - (void)badgeViews:(void (^)(UIView* badgeView, UILabel* badgeLabel, UIView* badgeBackground))block {
        if (block) {
            for (UIView* tabBarButton in self.subviews) {
                for (UIView* badgeView in tabBarButton.subviews) {
                    NSString* className = NSStringFromClass([badgeView class]);
    
                    if ([className rangeOfString:@"BadgeView"].location != NSNotFound) {
                        UILabel* badgeLabel;
                        UIView* badgeBackground;
    
                        for (UIView* badgeSubview in badgeView.subviews) {
                            NSString* className = NSStringFromClass([badgeSubview class]);
    
                            if ([badgeSubview isKindOfClass:[UILabel class]]) {
                                badgeLabel = (UILabel *)badgeSubview;
    
                            } else if ([className rangeOfString:@"BadgeBackground"].location != NSNotFound) {
                                badgeBackground = badgeSubview;
                            }
                        }
    
                        block(badgeView, badgeLabel, badgeBackground);
                    }
                }
            }
        }
    }
    

    Then when you're ready to call it, it'll look like this.

    [self.tabBar badgeViews:^(UIView *badgeView, UILabel *badgeLabel, UIView *badgeBackground) {
    
    }];
    

    EDIT: 11/16/15

    It's been brought to my attention that some people need a little more clarity on what's happening in this code. The for loops are searching for a few views which are not publicly accessible. By checking if the views class name contains a part of the expected name, it's ensuring to reach the intended view while not setting off any possible red flags by Apple. Once everything has been located, a block is executed with easy access to these views.

    It's noteworthy that the possibility exists for this code to stop working in a future iOS update. For example these internal views could one day acquire different class names. However the chances of that are next to none since even internally Apple rarely refactors classes to this nature. But even if they were to, it would be something along the title of UITabBarBadgeView, which would still reach the expected point in code. Being that iOS9 is well out the door and this code is still working as intended, you can expect this problem to never arise.

    0 讨论(0)
  • 2020-12-05 01:06

    Swift 3 Here is an updated version of @Kirualex's answer (who improved on @TimWhiting's answer) for Swift 3.

    extension UITabBarController {
    
        func setBadges(badgeValues: [Int]) {
    
            for view in self.tabBar.subviews {
                if view is CustomTabBadge {
                    view.removeFromSuperview()
                }
            }
    
            for index in 0...badgeValues.count-1 {
                if badgeValues[index] != 0 {
                    addBadge(index: index, value: badgeValues[index], color: UIColor.blue, font: UIFont(name: "Helvetica-Light", size: 11)!)
                }
            }
        }
    
        func addBadge(index: Int, value: Int, color: UIColor, font: UIFont) {
            let badgeView = CustomTabBadge()
    
            badgeView.clipsToBounds = true
            badgeView.textColor = UIColor.white
            badgeView.textAlignment = .center
            badgeView.font = font
            badgeView.text = String(value)
            badgeView.backgroundColor = color
            badgeView.tag = index
            tabBar.addSubview(badgeView)
    
            self.positionBadges()
        }
    
        override open func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            self.positionBadges()
        }
    
        // Positioning
        func positionBadges() {
    
            var tabbarButtons = self.tabBar.subviews.filter { (view: UIView) -> Bool in
                return view.isUserInteractionEnabled // only UITabBarButton are userInteractionEnabled
            }
    
            tabbarButtons = tabbarButtons.sorted(by: { $0.frame.origin.x < $1.frame.origin.x })
    
            for view in self.tabBar.subviews {
                if view is CustomTabBadge {
                    let badgeView = view as! CustomTabBadge
                    self.positionBadge(badgeView: badgeView, items:tabbarButtons, index: badgeView.tag)
                }
            }
        }
    
        func positionBadge(badgeView: UIView, items: [UIView], index: Int) {
    
            let itemView = items[index]
            let center = itemView.center
    
            let xOffset: CGFloat = 12
            let yOffset: CGFloat = -14
            badgeView.frame.size = CGSize(width: 17, height: 17)
            badgeView.center = CGPoint(x: center.x + xOffset, y: center.y + yOffset)
            badgeView.layer.cornerRadius = badgeView.bounds.width/2
            tabBar.bringSubview(toFront: badgeView)
        }
    }
    
    class CustomTabBadge: UILabel {}
    
    0 讨论(0)
  • 2020-12-05 01:10

    Hm...it's very easy. [[self tabBarItem] setBadgeColor:[UIColor greenColor]];

    0 讨论(0)
  • 2020-12-05 01:13

    UITabBarItem has this available since iOS 10.

    var badgeColor: UIColor? { get set }
    

    It's also available via appearence.

    if #available(iOS 10, *) {
       UITabBarItem.appearance().badgeColor = .green
    }
    

    reference docs: https://developer.apple.com/reference/uikit/uitabbaritem/1648567-badgecolor

    0 讨论(0)
提交回复
热议问题