Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS TabBar item title issue in iOS13

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)
}
like image 705
Sanjeev Pant Avatar asked Oct 31 '19 10:10

Sanjeev Pant


3 Answers

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
}
like image 184
chungchung Avatar answered Nov 19 '22 17:11

chungchung


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.

like image 11
matt Avatar answered Nov 19 '22 17:11

matt


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.

like image 6
Nikunj Acharya Avatar answered Nov 19 '22 18:11

Nikunj Acharya