iosswiftuikituitabbaruiappearance

Setting a UITabBarAppearance breaks UITabBarItem appearance proxy font size when selecting tabs


The following, which sets the title text appearance proxy to use a big font, works as expected, and the UITabBarItems retain their big font when you select them:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // UITabBar.appearance().standardAppearance = UITabBarAppearance()
                
        let bigFont = UIFont.systemFont(ofSize: 20)
        UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font: bigFont], for: .normal)
        UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font: bigFont], for: .selected)
        
        return true
    }

enter image description here


But when you set a UITabBarAppearance on the UITabBar appearance proxy, the font size is broken when you select tabs:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        UITabBar.appearance().standardAppearance = UITabBarAppearance()
                
        let bigFont = UIFont.systemFont(ofSize: 20)
        UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font: bigFont], for: .normal)
        UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font: bigFont], for: .selected)
        
        return true
    }

enter image description here



Question:

Does anyone know why setting a UITabBarAppearance would break the setTitleTextAttributes font size choice?


Background info:

The reason I'm using setting the standardAppearance on the UITabBar is because in my actual project I'm using the following code to retain the old look of the tab bar, and not the new one which goes transparent when there is no content on the screen (and messes up the app design).

If there is a way to achieve that without breaking the font size, then that could be a potential "fix" :)

if #available(iOS 13.0, *) {
    let tabBarAppearance = UITabBarAppearance()
    tabBarAppearance.configureWithDefaultBackground()
    UITabBar.appearance().standardAppearance = tabBarAppearance
    if #available(iOS 15.0, *) {
        UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
    }
}

Solution

  • Okay I figured out a fix (kinda feels like I'm just using Stack Overflow to rubber duck at this point 😅).

    The following will retain the correct font size after selecting tabs.

    Note it is still necessary to set the attributes directly on the UITabBarItem (the UITabBarItem.appearance().setTitleTextAttributes... lines), because otherwise the tabs won't start with the correct font size, they will only change to it after being selected by the user.

    Also note if you're setting the standardAppearance on the tab bar, you'll probably also want to set the scrollEdgeAppearance - as I did in the last snippet of code in the original question.

        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            
            let bigFont = UIFont.systemFont(ofSize: 20)
            let textAttributes = [NSAttributedString.Key.font: bigFont]
            
            UITabBarItem.appearance().setTitleTextAttributes(textAttributes, for: .normal)
            UITabBarItem.appearance().setTitleTextAttributes(textAttributes, for: .selected)
            
            let tabBarItemAppearance = UITabBarItemAppearance()
            tabBarItemAppearance.normal.titleTextAttributes = textAttributes
            tabBarItemAppearance.selected.titleTextAttributes = textAttributes
            
            let tabBarAppearance = UITabBarAppearance()
            tabBarAppearance.inlineLayoutAppearance = tabBarItemAppearance
            tabBarAppearance.stackedLayoutAppearance = tabBarItemAppearance
            tabBarAppearance.compactInlineLayoutAppearance = tabBarItemAppearance
            
            UITabBar.appearance().standardAppearance = tabBarAppearance
            
            return true
        }