8

This is how my Tabbar is looking right now.

enter image description here

How do I move that badge so that it overlaps the top right of the bell icon? Any help is appreciated.

Drunken Daddy
  • 7,326
  • 14
  • 70
  • 104
  • see this http://stackoverflow.com/questions/24236823/how-to-adjust-tab-bar-badge-position – Anbu.Karthik Aug 16 '16 at 10:59
  • Possible duplicate of [iOS 7 UITabBar badge position](http://stackoverflow.com/questions/19165671/ios-7-uitabbar-badge-position) – chrs Aug 16 '16 at 14:57

5 Answers5

7

Here is a simple example with a red spot githubGist. And of course, you can custom the your own badgeView = UIView() if you wanna add a label inside.

Swift 4.2

fileprivate let tabBarItemTag: Int = 10090
extension UITabBar {
    public func addItemBadge(atIndex index: Int) {
        guard let itemCount = self.items?.count, itemCount > 0 else {
            return
        }
        guard index < itemCount else {
            return
        }
        removeItemBadge(atIndex: index)

        let badgeView = UIView()
        badgeView.tag = tabBarItemTag + Int(index)
        badgeView.layer.cornerRadius = 5
        badgeView.backgroundColor = UIColor.red

        let tabFrame = self.frame
        let percentX = (CGFloat(index) + 0.56) / CGFloat(itemCount)
        let x = (percentX * tabFrame.size.width).rounded(.up)
        let y = (CGFloat(0.1) * tabFrame.size.height).rounded(.up)
        badgeView.frame = CGRect(x: x, y: y, width: 10, height: 10)
        addSubview(badgeView)
    }

    //return true if removed success.
    @discardableResult
    public func removeItemBadge(atIndex index: Int) -> Bool {
        for subView in self.subviews {
            if subView.tag == (tabBarItemTag + index) {
                subView.removeFromSuperview()
                return true
            }
        }
        return false
    }
}
boog
  • 1,813
  • 3
  • 18
  • 21
6

try this:

func repositionBadge(tabIndex: Int){

    for badgeView in self.tabBarController!.tabBar.subviews[tabIndex].subviews {

        if NSStringFromClass(badgeView.classForCoder) == "_UIBadgeView" {
            badgeView.layer.transform = CATransform3DIdentity
            badgeView.layer.transform = CATransform3DMakeTranslation(-17.0, 1.0, 1.0)
        }
    }
}

pay attention, tabIndex starts from 1

Marco Santarossa
  • 4,058
  • 1
  • 29
  • 49
2

When using iOS 13 or newer, the badge position can be changed by assigning an UITabBarItemAppearance object to the item appearance properties of an UITabBarAppearance object, and assign this to the appearance property of your tabBar control.

Example:

 let itemAppearance = UITabBarItemAppearance()
 itemAppearance.normal.badgePositionAdjustment.horizontal = 10
    
 let appearance = UITabBarAppearance()
 appearance.stackedLayoutAppearance = itemAppearance
 appearance.inlineLayoutAppearance = itemAppearance
 appearance.compactInlineLayoutAppearance = itemAppearance

 tabBar.standardAppearance = appearance
Ely
  • 8,259
  • 1
  • 54
  • 67
1

Based on Marco Santarossa's answer, I updated it by making it into a UITabBarController extension, with a few additional tweaks:

extension UITabBarController {
    func repositionBadgeLayer(_ badgeView: UIView) {
        if NSStringFromClass(badgeView.classForCoder) == "_UIBadgeView" {
            badgeView.layer.transform = CATransform3DIdentity
            badgeView.layer.transform = CATransform3DMakeTranslation(-17.0, 1.0, 1.0)
        }
    }

    func repositionBadges(tab: Int? = nil) {
        if let tabIndex = tab {
            for badgeView in self.tabBar.subviews[tabIndex].subviews {
                repositionBadgeLayer(badgeView)
            }
        } else {
            for tabBarSubviews in self.tabBar.subviews {
                for badgeView in tabBarSubviews.subviews {
                    repositionBadgeLayer(badgeView)
                }
            }
        }
    }
}

Now you can use it on your custom UITabBarController class, simply call:

  1. repositionBadges() to apply on every tab bar item available in the tab bar

    or

  2. repositionBadges(0) with 0 referring to the tab bar item index, for selective application

Dan
  • 810
  • 2
  • 11
  • 29
1

I am not sure transforming the badge layer can be solition since it has some defects:

  • it is reset after tab selection
  • it keeps transfroming once badge lable changes

I came up with another solution

if UIDevice.current.userInterfaceIdiom == .pad {
        self.standatartTabBarAppearance.inlineLayoutAppearance.normal.badgePositionAdjustment.horizontal = .init(16.0)
        self.standatartTabBarAppearance.stackedLayoutAppearance.normal.badgePositionAdjustment.horizontal = .init(16.0)
        self.standatartTabBarAppearance.compactInlineLayoutAppearance.normal.badgePositionAdjustment.horizontal = .init(16.0)
    }
self.tabBar.standardAppearance = self.standatartTabBarAppearance
Riddik
  • 2,565
  • 1
  • 11
  • 21