This is how my Tabbar is looking right now.
How do I move that badge so that it overlaps the top right of the bell icon? Any help is appreciated.
This is how my Tabbar is looking right now.
How do I move that badge so that it overlaps the top right of the bell icon? Any help is appreciated.
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
}
}
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
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
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:
repositionBadges()
to apply on every tab bar item available in the tab bar
or
repositionBadges(0)
with 0
referring to the tab bar item index, for selective application
I am not sure transforming the badge layer can be solition since it has some defects:
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