4

I want to change the badge text color and font of my tab bar item using setBadgeTextAttributes in my tabBarViewController. So I use my code:

for (UITabBarItem *tabBarItem in self.tabBar.items){
        [tabBarItem setBadgeColor:[UIColor redColor];
        [tabBarItem setBadgeTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                        [UIFont fontWithName:@"Helvetica-Bold" size:26.0], NSFontAttributeName,
                                        [UIColor greenColor], NSForegroundColorAttributeName,
                                        nil] forState:UIControlStateNormal];
}

But it only change the badge text color, but not the font. How can I fix it?

Please and thanks~

star chen
  • 43
  • 1
  • 3

3 Answers3

3
let attribute : [String : Any] = [NSAttributedStringKey.foregroundColor.rawValue : UIColor.black]
self.tabBarController?.tabBar.items?[tabBarIndex].setBadgeTextAttributes(attribute, for: .normal)

This is how I did it

Use the rawValue

Kelvin Fok
  • 621
  • 7
  • 9
0

Try put your code inside viewDidAppear like this:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    if let notificationItem = self.tabBar.items?.last {
        notificationItem.badgeValue = "\(12)"

        if #available(iOS 10.0, *) {
            notificationItem.badgeColor = .red
            notificationItem.setBadgeTextAttributes([
                NSForegroundColorAttributeName: UIColor.green,
                NSFontAttributeName: UIFont(name: "Helvetica-Bold", size: 10)!
                ], for: .normal)
        }
    }
}
buxik
  • 2,583
  • 24
  • 31
  • Dear Buxik thanks, this works fine for changing badge font color, but it doesn't change font. is there anyway to change the font? – Niloufar Jan 20 '19 at 08:55
0

On iOS 12, it seems setting the font using setBadgeTextAttributes does not work. Here is a solution based on this answer:

extension UITabBar {
        func setBadge(value: String?, at index: Int, withConfiguration configuration: TabBarBadgeConfiguration = TabBarBadgeConfiguration()) {
            let existingBadge = subviews.first { ($0 as? TabBarBadge)?.hasIdentifier(for: index) == true }
            existingBadge?.removeFromSuperview()

            guard let tabBarItems = items,
                let value = value else { return }

            let itemPosition = CGFloat(index + 1)
            let itemWidth = frame.width / CGFloat(tabBarItems.count)
            let itemHeight = frame.height

            let badge = TabBarBadge(for: index)
            badge.frame.size = configuration.size
            badge.center = CGPoint(x: (itemWidth * itemPosition) - (0.5 * itemWidth) + configuration.centerOffset.x,
                                   y: (0.5 * itemHeight) + configuration.centerOffset.y)
            badge.layer.cornerRadius = 0.5 * configuration.size.height
            badge.clipsToBounds = true
            badge.textAlignment = .center
            badge.backgroundColor = configuration.backgroundColor
            badge.font = configuration.font
            badge.textColor = configuration.textColor
            badge.text = value

            addSubview(badge)
        }
    }

    class TabBarBadge: UILabel {
        var identifier: String = String(describing: TabBarBadge.self)

        private func identifier(for index: Int) -> String {
            return "\(String(describing: TabBarBadge.self))-\(index)"
        }

        convenience init(for index: Int) {
            self.init()
            identifier = identifier(for: index)
        }

        func hasIdentifier(for index: Int) -> Bool {
            let has = identifier == identifier(for: index)
            return has
        }
    }

    class TabBarBadgeConfiguration {
        var backgroundColor: UIColor = .red
        var centerOffset: CGPoint = .init(x: 12, y: -9)
        var size: CGSize = .init(width: 17, height: 17)
        var textColor: UIColor = .white
        var font: UIFont! = .systemFont(ofSize: 11) {
            didSet { font = font ?? .systemFont(ofSize: 11) }
        }

        static func construct(_ block: (TabBarBadgeConfiguration) -> Void) -> TabBarBadgeConfiguration {
            let new = TabBarBadgeConfiguration()
            block(new)
            return new
        }
    }
Dani Avram
  • 201
  • 1
  • 9
  • This will only work in horizontally compact device. iPad OS or landscape orientation in iOS have different item spacing and it seems there's no way to figure how big that is unless I use private APIs. – Ryan Jun 15 '20 at 16:40