【问题标题】:Is it possible to change UITabBarItem badge color是否可以更改 UITabBarItem 徽章颜色
【发布时间】:2012-10-31 18:03:03
【问题描述】:

我想更改UITabBarItem徽章的背景颜色,但找不到任何有关如何制作的资源。

【问题讨论】:

    标签: iphone objective-c ios uitabbar uitabbaritem


    【解决方案1】:

    UITabBarItem 从 iOS 10 开始提供此功能。

    var badgeColor: UIColor? { get set }
    

    它也可以通过外观获得。

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

    参考文档: https://developer.apple.com/reference/uikit/uitabbaritem/1648567-badgecolor

    【讨论】:

    • 我还想支持iOS9怎么办?我需要在respondsToSelector resp #available 电话中附上这个吗?
    • 我刚刚意识到我从未回答过这个问题@jens。这可能对这个问题本身不再有用,但可能对类似的事情有用。但如果 api 还不支持该功能,则必须在“else”中使用其他方式。在这种情况下,请使用这些答案中显示的任何其他方式。
    【解决方案2】:

    现在在 iOS 10 及更高版本中原生支持更改徽章颜色,使用 UITabBarItem 中的 badgeColor 属性。有关该物业的更多信息,请参阅apple docs

    例子:

    • 斯威夫特 3:myTab.badgeColor = UIColor.blue
    • 目标-C:[myTab setBadgeColor:[UIColor blueColor]];

    【讨论】:

    • if ([myTab respondsToSelector:@selector(setBadgeColor:)]) { [myTab setBadgeColor:[UIColor blueColor]]; }
    • 你能解释一下这是如何实现的吗?我有点困惑。
    【解决方案3】:

    我为我的应用编写了这段代码,但我只在 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];
                    }
                }
            }
        }
    }
    

    您只能使用图像而不是颜色来更新徽章背景。如果您想以某种方式更新它,我还公开了徽章标签。

    需要注意的是,这段代码必须在设置tabBarItem.badgeValue后调用!

    编辑:2014 年 4 月 14 日

    上面的代码在任何地方调用时都可以在 iOS 7 中运行。要让它在 iOS 7.1 中工作,请在视图控制器 -viewWillLayoutSubviews 中调用它。

    编辑:2014 年 12 月 22 日

    这是我目前正在使用的更新后的 sn-p。为简单起见,我将代码放在类别扩展中。

    - (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);
                    }
                }
            }
        }
    }
    

    然后当你准备好调用它时,它会是这样的。

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

    编辑:2015 年 11 月 16 日

    我注意到有些人需要更清楚地了解这段代码中发生的事情。 for 循环正在搜索一些不可公开访问的视图。通过检查视图类名称是否包含预期名称的一部分,可以确保到达预期视图,同时不会引发 Apple 的任何可能的危险信号。一旦找到所有内容,就可以轻松访问这些视图来执行一个块。

    值得注意的是,此代码有可能在未来的 iOS 更新中停止工作。例如,这些内部视图有朝一日可能会获得不同的类名。然而,这种可能性几乎为零,因为即使在内部,Apple 也很少将类重构为这种性质。但即使他们这样做,它也将是 UITabBarBadgeView 的标题,它仍然会达到代码中的预期点。由于 iOS9 已经推出,而且这段代码仍然可以按预期工作,因此您可以期望这个问题永远不会出现。

    【讨论】:

    • 提供的解决方案适用于iOS 7,但不适用于iOS7.1。 7.1可以做些什么吗?
    • 确保它在你的视图控制器中被调用-viewWillLayoutSubviews
    • @jeffamaphone OP 问道,“有可能吗”。他们从来没有要求一个不会中断的实现。你给我投反对票的理由是不充分的。恳请您扭转行动。
    • 建议:将if (block) 条件放在方法的顶部:没有block 参数,此方法无论如何都不会执行任何操作。
    • 我会主动投入两美分。 1) 私有视图或视图层次结构不是私有 API。苹果一直以来都在做出这种区分。 2) Apple 的指导方针与 SO 答案无关,除非问题明确要求 Apple 可以接受的答案。 3)最好注意一个答案可能不可接受,但它可能不值得投反对票。只需发表评论并继续前进。
    【解决方案4】:

    我有同样的问题,并通过创建一个小类别将 BadgeView 替换为您可以轻松自定义的 UILabel 来解决它。

    https://github.com/enryold/UITabBarItem-CustomBadge/

    【讨论】:

    • 这会被苹果拒绝吗?
    • 不,我有一个使用这个库的在线应用程序。
    • 您正在访问那里的私有财产。 if([str isEqualToString:@"_UIBadgeView"] 。Apple 怎么不拒绝?权限变了吗?
    • 几年前我在一个项目中使用过它,Apple 从不拒绝它。
    【解决方案5】:

    对于使用 Swift 的人,我设法改进了 TimWhiting 的答案,以便让徽章视图在任何屏幕尺寸和任何方向上都能正常工作。

     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, value: badgeValues[index], color:UIColor(paletteItem: .Accent), font: UIFont(name: Constants.ThemeApp.regularFontName, size: 11)!)
                }
            }
        }
    
        func addBadge(index: Int, value: Int, color: UIColor, font: UIFont) {
            let badgeView = CustomTabBadge()
    
            badgeView.clipsToBounds = true
            badgeView.textColor = UIColor.whiteColor()
            badgeView.textAlignment = .Center
            badgeView.font = font
            badgeView.text = String(value)
            badgeView.backgroundColor = color
            badgeView.tag = index
            tabBar.addSubview(badgeView)
    
            self.positionBadges()
        }
    
        override public func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            self.positionBadges()
        }
    
        // Positioning
        func positionBadges() {
    
            var tabbarButtons = self.tabBar.subviews.filter { (view: UIView) -> Bool in
                return view.userInteractionEnabled // only UITabBarButton are userInteractionEnabled
            }
    
            tabbarButtons = tabbarButtons.sort({ $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, 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 = CGSizeMake(17, 17)
            badgeView.center = CGPointMake(center.x + xOffset, center.y + yOffset)
            badgeView.layer.cornerRadius = badgeView.bounds.width/2
            tabBar.bringSubviewToFront(badgeView)
        }
    }
    
    class CustomTabBadge: UILabel {}
    

    【讨论】:

      【解决方案6】:

      不,您不能更改颜色,但您可以使用自己的徽章。在文件范围内添加此扩展名,您可以根据需要自定义徽章。只需在您的任何根视图控制器中调用self.tabBarController!.setBadges([1,0,2])

      需要明确的是,标签栏包含三个项目,徽章值从左到右。

      extension UITabBarController {
          func setBadges(badgeValues:[Int]){
      
              var labelExistsForIndex = [Bool]()
      
              for value in badgeValues {
                  labelExistsForIndex.append(false)
              }
      
              for view in self.tabBar.subviews {
                  if view.isKindOfClass(PGTabBadge) {
                      let badgeView = view as! PGTabBadge
                      let index = badgeView.tag
      
                      if badgeValues[index]==0 {
                          badgeView.removeFromSuperview()
                      }
      
                      labelExistsForIndex[index]=true
                      badgeView.text = String(badgeValues[index])
      
                  }
              }
      
              for var i=0;i<labelExistsForIndex.count;i++ {
                  if labelExistsForIndex[i] == false {
                      if badgeValues[i] > 0 {
                          addBadge(i, value: badgeValues[i], color:UIColor(red: 4/255, green: 110/255, blue: 188/255, alpha: 1), font: UIFont(name: "Helvetica-Light", size: 11)!)
                      }
                  }
              }
      
      
          }
      
          func addBadge(index:Int,value:Int, color:UIColor, font:UIFont){
      
              let itemPosition = CGFloat(index+1)
              let itemWidth:CGFloat = tabBar.frame.width / CGFloat(tabBar.items!.count)
      
              let bgColor = color
      
              let xOffset:CGFloat = 12
              let yOffset:CGFloat = -9
      
              var badgeView = PGTabBadge()
              badgeView.frame.size=CGSizeMake(17, 17)
              badgeView.center=CGPointMake((itemWidth * itemPosition)-(itemWidth/2)+xOffset, 20+yOffset)
              badgeView.layer.cornerRadius=badgeView.bounds.width/2
              badgeView.clipsToBounds=true
              badgeView.textColor=UIColor.whiteColor()
              badgeView.textAlignment = .Center
              badgeView.font = font
              badgeView.text = String(value)
              badgeView.backgroundColor = bgColor
              badgeView.tag=index
              tabBar.addSubview(badgeView)
      
          }
      }
      
      class PGTabBadge: UILabel {
      
      }
      

      【讨论】:

        【解决方案7】:

        Swift 3 这是 Swift 3 的 @Kirualex 答案的更新版本(改进了 @TimWhiting 的答案)。

        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 {}
        

        【讨论】:

          【解决方案8】:

          似乎没有。您只能设置该值。 来自 Apple 的文档徽章是:

          显示在项目右上角的文本,带有 环绕红色椭圆形。

          【讨论】:

            【解决方案9】:

            您需要在索引处指定标签项以更改徽章颜色,#available in iOS 10,

                if #available(iOS 10.0, *) 
                {
                    self.kAppTabBarController.tabBar.items![1].badgeColor = YOUR_COLOR
                }
            

            【讨论】:

              【解决方案10】:

              您现在也可以在情节提要中执行此操作,方法是选择您的标签栏项目并转到属性检查器。

              【讨论】:

                【解决方案11】:

                是的,但唯一可能的解决方案是创建自定义标签栏并创建自定义标签栏徽章图标。您会发现许多用于创建自定义标签栏的文章/代码。

                【讨论】:

                  【解决方案12】:
                  // 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];
                                      }
                                  }
                              }
                          }
                      }
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    嗯...这很容易。 [[self tabBarItem] setBadgeColor:[UIColor greenColor]];

                    【讨论】:

                      【解决方案14】:

                      由于 iOS 15 有不同的方法,我的情况是什么:

                      let appearance = UITabBarAppearance()
                      appearance.configureWithTransparentBackground()
                              
                      let barAppearance = UITabBarItemAppearance()
                              
                      barAppearance.normal.badgeBackgroundColor = .green
                      barAppearance.normal.badgeTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red]
                      
                      appearance.stackedLayoutAppearance = barAppearance
                           
                      tabBar.standardAppearance = appearance
                      

                      【讨论】:

                        【解决方案15】:

                        看看这里@@UITabbarItem-CustomBadge

                        下面是完整的演示

                        如果要使用默认实现,只需要两行代码

                        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
                        
                          //supplying the animation parameter
                          [UITabBarItem setDefaultAnimationProvider:[[DefaultTabbarBadgeAnimation alloc] init]];
                          [UITabBarItem setDefaultConfigurationProvider:[[DefaultSystemLikeBadgeConfiguration alloc] init]];
                        
                          //rest of your code goes following...
                        
                          return YES;
                        }
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2021-07-30
                          • 2015-06-03
                          • 2016-12-22
                          • 2022-01-08
                          • 1970-01-01
                          相关资源
                          最近更新 更多