How to adjust tab bar badge position?

偶尔善良 提交于 2019-12-01 04:26:21

I found Kateryna's answer to be useful in putting me on the right track, but I had to update it a little:

func repositionBadge(tab: Int){

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

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

}

Please note the tab integer is NOT zero-indexed, so the first tab will be number 1, the 2nd number 2, etc.

When you update your badge value, add such a method:

func updateBadge(#value: UInt, tabBarItemTag: Int) {
     self.viewControllerForTag(tabBarItemTag)?.tabBarItem.badgeValue = value
     for badgeView in (tabBar.subviews[tabBarItemTag] as! UIView).subviews {
         let className = "\(_stdlib_getDemangledTypeName(badgeView))"
         if className.rangeOfString("BadgeView").location != NSNotFound {
             badgeView.layer.transform = CATransform3DIdentity
             badgeView.layer.transform = CATransform3DMakeTranslation(0.0, 10.0, 20.0)
         }
     }
}

You need to play a bit with a second CATransform3DMakeTranslation to make right positioning. In this code badge moves a bit on bottom/left. First CATransform3DMakeTranslation is needed to pretend badge moving. It is a Swift code, but you can convert it to Objective-C easily.

Badge align to your tab bar image by default.If you add large image as tab bar item image you can adjust it's using following code.

for tabBarButton in self.tabBar.subviews{
        for badgeView in tabBarButton.subviews{
        var className=NSStringFromClass(badgeView.classForCoder)
            if  className == "_UIBadgeView"
            {
                badgeView.layer.transform = CATransform3DIdentity
                badgeView.layer.transform = CATransform3DMakeTranslation(-17.0, 1.0, 1.0)
            }
        }
    }

In Objective-C:

    for (UIView *tabBarButton in self.navigationController.tabBarController.tabBar.subviews)
    {
        for (UIView *badgeView in tabBarButton.subviews)
        {
            NSString *className = NSStringFromClass([badgeView class]);

            // Looking for _UIBadgeView
            if ([className rangeOfString:@"BadgeView"].location != NSNotFound)
            {
                badgeView.layer.transform = CATransform3DIdentity;
                badgeView.layer.transform = CATransform3DMakeTranslation(-5.0, 1.0, 1.0);
            }
        }
    }

In C# Xamarin

void RepositionBadge(int tab)
{
    foreach (var badgeView in TabBar.Subviews[tab].Subviews)
    {
        if (badgeView.Class.Name == "_UIBadgeView")
        {
            badgeView.Layer.Transform = CATransform3D.Identity;
            badgeView.Layer.Transform = CATransform3D.MakeTranslation(-10.0f, 1.0f, 1.0f);
        }
    }
}

Swift 4, 5

I've created an extension for UITabBar which gets the badge view and the badge's label the swifty way:

extension UITabBar {
    func badgeViewForItem(at index: Int) -> UIView? {
        guard subviews.count > index else {
            return nil
        }
        return subviews[index].subviews.first(where: { NSStringFromClass($0.classForCoder) == "_UIBadgeView" })
    }

    func labelForItem(at index: Int) -> UILabel? {
        guard subviews.count > index else {
            return nil
        }
        return badgeViewForItem(at: index)?.subviews.first(where: { $0 is UILabel }) as? UILabel
    }
}

And then you can do something like:

let firstItemBadgeView = badgeViewForItem(at: 0)!
// Do something with the badge view like setting the border, background color ...
// ex: firstItemBadgeView.backgroundColor = UIColor.clear
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!