iOS TabBar item title issue in iOS13
Asked Answered
P

5

14

I am having issue in tabBar title for iOS13 on compiling from Xcode 11.It works perfect whle compiling from Xcode 10.Please find the screenshot for the issue and below is the code for customising the tabBar.

enter image description here

The code is

self.tabBar.isTranslucent = true
self.tabBar.tintColor = UIColor.white
UITabBarItem.appearance().badgeColor = Constant.Colors.colorFF1744
if #available(iOS 13, *) {
    let appearance = UITabBarAppearance.init()
    appearance.stackedLayoutAppearance.normal.titleTextAttributes = [NSAttributedString.Key.font:UIFont(name: Constant.FontNames.RubikRegular, size: Constant.FontSize.P5heading)!,NSAttributedString.Key.foregroundColor:Constant.Colors.color8D8D8D]
    appearance.stackedLayoutAppearance.selected.titleTextAttributes = [NSAttributedString.Key.font:UIFont(name: Constant.FontNames.RubikRegular, size:Constant.FontSize.P5heading)!,NSAttributedString.Key.foregroundColor:Constant.Colors.colorFF1744]
    appearance.stackedItemPositioning = .automatic
    self.tabBar.standardAppearance = appearance
} else {
    UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font:UIFont(name: Constant.FontNames.RubikRegular, size: Constant.FontSize.P5heading)!, NSAttributedString.Key.foregroundColor:Constant.Colors.color8D8D8D], for: .normal)
    UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font:UIFont(name: Constant.FontNames.RubikRegular, size: Constant.FontSize.P5heading)!, NSAttributedString.Key.foregroundColor:Constant.Colors.colorFF1744], for: .selected)
}
Prostitute answered 31/10, 2019 at 10:21 Comment(0)
A
11

Remove your if #available(iOS 13, *) and do this the same way you were doing it in iOS 12. The new way, UITabBarAppearance, is full of bugs. Avoid it until they are fixed.

Angloamerican answered 31/10, 2019 at 10:29 Comment(11)
ok , but my need to use UITabBarAppearance was due to the selected tab bar title color was not showing in iOS 13 when compiled from Xcode 11.Prostitute
Well maybe that is a different bug. But it is not what you asked. You asked about the truncated titles. I’ve seen that and I can prove it’s a bug. That is my answer.Angloamerican
You can say UITabBar.appearance().unselectedItemTintColor = Constant.Colors.color8D8D8D to fix that. It will have other consequences but at least it fixes the text color. :)Angloamerican
@SanjeevPant were you able to solve the truncating title when using the new Appearance API?Heteroecious
@Heteroecious You cannot solve it. It’s a bug. That is what my answer tells you.Angloamerican
@Angloamerican Okay. I'm just confirming if maybe OP tried looking for other alternatives other than your answer. I'm not disregarding its likely a bug but since I can't find any other reference to back that up there's might be something else going on.Heteroecious
@Heteroecious It solved my problem and there were ripple effect from it. I agree, it is bug but there were some users who needed support for it.Prostitute
@Angloamerican (or anyone else) did you open a radar for this truncated text issue and Apple confirmed it's a bug?Portion
@valcanaia I filed a bug report. Apple never confirms anything. If you want more attention on this issue, file a report yourself. Apple has said that numbers matter.Angloamerican
@Angloamerican can you share the radar number so I can add a reference to it?Portion
@valcanaia That would be FB7336994 ("UITabBarItemAppearance features completely break tab bar") but I don't think that info will do you any good.Angloamerican
Y
6

It is bug in iOS 13 API, which initialise tabBarButtonItem's label with incorrect font size.

I tried to print font size of label via following code inside viewWillLayoutSubviews

override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        self.tabBar.subviews.forEach { (barButton) in
            if let label = barButton.subviews[1] as? UILabel{
                print(label.font ?? "NULL font")
            }
        }
    }

and it printed following log

<UICTFont: 0x7fa3c5d07350> font-family: ".SFUI-Medium"; font-weight: normal; font-style: normal; font-size: 10.00pt

It showed font family different than what I set via UITabBarAppearance. So I've used UITabBarItem.appearance(). After setting this property, I ran above code again and it showed me correct font family.

But What is happening inside? I think First UIKit will try to calculate bounds of label by default font size (It totally ignores font set by UITabBarAppearance). So bounding box calculated for label is also smaller and hence text gets truncated. But UIKit respects value set by UITabBarItem.appearance() and will calculate correct bounds for label.

I solved this problem with following approach.

class MainViewController: UITabBarController {


    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        self.updateTabBarAppearance()
        self.setupChildViewControllers()

    }

    fileprivate func setupChildViewControllers(){
        let vc1 = ViewController()
        vc1.tabBarItem = UITabBarItem(title: "Home", image: UIImage(named: "home"), selectedImage: UIImage(named: "home"))
        let viewControllerList = [vc1]
        self.viewControllers = viewControllerList.map { UINavigationController(rootViewController: $0) }
    }

    fileprivate func updateTabBarAppearance(){

        if #available(iOS 13.0, *){

            let tabBarAppearance = UITabBarAppearance()
            let tabBarItemAppearance = UITabBarItemAppearance(style: .stacked)

            tabBarItemAppearance.normal.titleTextAttributes = [
                .font: UIFont.themeFont(ofSize: 12, weight: .medium),
                .foregroundColor: UIColor(red: 31/255, green: 42/255, blue: 85/255, alpha: 0.5),
            ]

            tabBarItemAppearance.selected.titleTextAttributes = [
                .font: UIFont.themeFont(ofSize: 12, weight: .bold),
                .foregroundColor: UIColor(red: 7/255, green: 111/255, blue: 236/255, alpha: 1),
            ]

            tabBarAppearance.stackedLayoutAppearance = tabBarItemAppearance
            tabBar.standardAppearance = tabBarAppearance

        }else{

            tabBar.shadowImage = UIImage()
            tabBar.backgroundImage = UIImage()
            tabBar.backgroundColor = .white

        }


        // This is helping us to achive our effect
        // We are setting font of same size but higher (or same) weight than our actual font
        // This will create label bigger than actual size, so it does not gets truncated.
        // But by creating bigger label, text will be aligned left

        // To solve that see `viewWillLayoutSubviews` method

        UITabBarItem.appearance().setTitleTextAttributes([.font: UIFont.themeFont(ofSize: 12, weight: .bold)], for: .normal)
        UITabBarItem.appearance().setTitleTextAttributes([.font: UIFont.themeFont(ofSize: 12, weight: .bold)], for: .selected)
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        self.tabBar.subviews.forEach { (barButton) in
            if let label = barButton.subviews[1] as? UILabel{
                // We will find the label and make this center align
                label.textAlignment = .center
            }
        }
    }

}

Also check the viewWillLayoutSubviews implementation to make label content centre align.

Yasmeen answered 13/4, 2020 at 21:35 Comment(1)
Thanks for this solution, I was able to simplify the solution by just doing this: self.tabBar.subviews.forEach { if let label = $0.subviews[1] as? UILabel { label.lineBreakMode = .byClipping } }Fulkerson
A
4

I had a similar issue as your post. I needed to make the title bold when selected. But it became truncated, though the regular one didn't. My workaround was to give spaces to the both end of the text like "Category" -> " Category ".
My guess was the width of regular-font box is fixed, even though it became bold-font. And it worked for my case. It's not precisely matching the case, but you may try.

if #available(iOS 13, *) {
  let appearance = UITabBarAppearance()
  appearance.backgroundColor = UIColor.black
  appearance.stackedLayoutAppearance.normal.titleTextAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 9, weight: .regular), NSAttributedString.Key.foregroundColor: UIColor.lightGray]
  appearance.stackedLayoutAppearance.selected.titleTextAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 9, weight: .bold), NSAttributedString.Key.foregroundColor: UIColor.red]
  appearance.stackedItemPositioning = .automatic
  tabBar.standardAppearance = appearance
  tabBar.scrollEdgeAppearance = appearance
}
Abdication answered 17/3, 2020 at 6:48 Comment(1)
A simple hack which also came to my mind, but in fact you need just an empty space at the end of the word: "Category ". It is being cut-off only on the back (right side).Groschen
I
1

I have this problem when manually toggling dark mode:

class MyTabBarController: UITabBarController {
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.tabBar.subviews.forEach { (bar) in
            bar.subviews.compactMap {
                $0 as? UILabel
            }.forEach {
                $0.sizeToFit()
            }
        }
    }
}
Internalcombustion answered 23/6, 2022 at 2:58 Comment(2)
This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. To get notified when this question gets new answers, you can follow this question. Once you have enough reputation, you can also add a bounty to draw more attention to this question. - From ReviewRheinlander
I also had this problem when switching to dark mode, and solved it by overriding viewDidLayoutSubviews to force the Label to re-layout. I think this method can also solve all similar problemsInternalcombustion
P
-1

In my case setting the imageinsets in code caused the titles to clip, setting them in IB fixed the issue.

for item in tabBar.items ?? [] {
        item.imageInsets = UIEdgeInsets(top: 6, left: 6, bottom: 6, right: 6)
    }
Polygraph answered 10/5, 2022 at 14:55 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.