Change TabBarItem title font to bold in Swift for iOS
Solution 1
FOUND THE SOLUTION (Swift 3, XCode 8.1)
-
In Storyboard, give a unique Tag to each UITabBarItem you have: For every tab -> Select it and go to it's "Attributes Inspector" -> Give each one a unique number in the "Tag" field but you should not use zero (I used 1 through 4).
This sets us up for later, to identify which tab is pressed.
-
Create a new subclass of UITabBarController and then assign it: FILE -> New File -> iOS Cocoa Touch -> create a Subclass of UITabBarController. Assign the new .swift file to your UITabBarController under "Identity Inspector."
We will need custom logic in our UITabBarController.
-
Create a new subclass of UITabBarItem, assign the same file to all of your UITabBarItems: FILE -> New File -> iOS Cocoa Touch -> create a Subclass of UITabBarItem and assign the same one to all of your tabs.
We will need a shared custom logic in our tab bar items.
-
Add this code to your UITabBarItem subclass, it sets up the initial state (primary tab bold, the rest unselected) and will allow for programmatic tab changes as well:
class MyUITabBarItemSubclass: UITabBarItem { //choose initial state fonts and weights here let normalTitleFont = UIFont.systemFont(ofSize: 12, weight: UIFontWeightRegular) let selectedTitleFont = UIFont.systemFont(ofSize: 12, weight: UIFontWeightBold) //choose initial state colors here let normalTitleColor = UIColor.gray let selectedTitleColor = UIColor.black //assigns the proper initial state logic when each tab instantiates override func awakeFromNib() { super.awakeFromNib() //this tag # should be your primary tab's Tag* if self.tag == 1 { self.setTitleTextAttributes([NSFontAttributeName: selectedTitleFont, NSForegroundColorAttributeName: selectedTitleColor], for: UIControlState.normal) } else { self.setTitleTextAttributes([NSFontAttributeName: normalTitleFont, NSForegroundColorAttributeName: normalTitleColor], for: UIControlState.normal) } } }
Here we set up the initial state so that the tabs are set correctly when the app opens up, we'll take care of the physical tab presses in the next subclass.
-
Add this code to your UITabBarController subclass, it's the logic for assigning the correct states as you press on the tabs.
class MyUITabBarControllerSubclass: UITabBarController { //choose normal and selected fonts here let normalTitleFont = UIFont.systemFont(ofSize: 12, weight: UIFontWeightRegular) let selectedTitleFont = UIFont.systemFont(ofSize: 12, weight: UIFontWeightBold) //choose normal and selected colors here let normalTitleColor = UIColor.gray let selectedTitleColor = UIColor.black //the following is a delegate method from the UITabBar protocol that's available //to UITabBarController automatically. It sends us information every //time a tab is pressed. Since we Tagged our tabs earlier, we'll know which one was pressed, //and pass that identifier into a function to set our button states for us override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { setButtonStates(itemTag: item.tag) } //the function takes the tabBar.tag as an Int func setButtonStates (itemTag: Int) { //making an array of all the tabs let tabs = self.tabBar.items //looping through and setting the states var x = 0 while x < (tabs?.count)! { if tabs?[x].tag == itemTag { tabs?[x].setTitleTextAttributes([NSFontAttributeName: selectedTitleFont, NSForegroundColorAttributeName: selectedTitleColor], for: UIControlState.normal) } else { tabs?[x].setTitleTextAttributes([NSFontAttributeName: normalTitleFont, NSForegroundColorAttributeName: normalTitleColor], for: UIControlState.normal) } x += 1 } } }
It looks like this was such a pain because for some reason the tabs do not recognize state changes into ".Selected". We had to do everything by working with .Normal states only - basically detecting the state changes ourselves.
- You can programmatically change the tabs and still detect state changes by... I'll update this later if anyone has an interest, just ask.
Hope this helped!
Solution 2
I've faced the same issue when tried to change font of selected item. Looks like titleTextAttributes' font parameter is only useful when setting them to normal state. That's why I implemented UITabBarControllerDelegate
where I update attributes for currently selected item. You should call updateSelection()
method after UITabBarController
s loadView()
too. Or you can call updateSelection()
method in overridden selectedItem
setter.
extension TabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
updateSelection()
}
func updateSelection() {
let normalFont = Fonts.Lato.light.withSize(10)
let selectedFont = Fonts.Lato.bold.withSize(10)
viewControllers?.forEach {
let selected = $0 == self.selectedViewController
$0.tabBarItem.setTitleTextAttributes([.font: selected ? selectedFont : normalFont], for: .normal)
}
}
}
Solution 3
Build Settings\Swift Language Version: 4.1
General\Deployment Target: 10.3
import UIKit
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let attrsNormal = [NSAttributedStringKey.foregroundColor : UIColor.black,
NSAttributedStringKey.font : UIFont(name: "Arial", size: 14)!]
UITabBarItem.appearance().setTitleTextAttributes(attrsNormal,
for: UIControlState.normal)
let attrsSelected = [NSAttributedStringKey.foregroundColor : UIColor.red,
NSAttributedStringKey.font : UIFont(name: "Arial", size: 14)!]
UITabBarItem.appearance().setTitleTextAttributes(attrsSelected,
for: UIControlState.selected)
}
...
}
Solution 4
The problem is that the state of tabBarItem0
is not changed to Selected
. Because this is UITabBarItem
which represents a single element of a UITabBar
. So, you can not directly change the status using UITabBarItem
API. You have to change it state by assigning selectedItem
.
This information is gained from documentation and I suggest all programmers to have skills like this. Hopefully, this will help.
Solution 5
UITabBarItem.appearance().setTitleTextAttributes(
[NSFontAttributeName: UIFont(name:"your_font_name", size:11)!,
NSForegroundColorAttributeName: UIColor(rgb: 0x929292)],
forState: .Normal)
Related videos on Youtube
Thomas Kremmel
Updated on September 15, 2022Comments
-
Thomas Kremmel almost 2 years
I'm trying to set the font weight of a selected tab bar item to bold font. It seems as it has no effect. Any idea what is wrong.
forState: .Normal
works as expected,forState: .Selected
has no effect.let tabBarItem0 = tabBar.items![0] as! UITabBarItem var selectedImage0 : UIImage = UIImage(named:"ic_tabbar_item_one")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal) var fontLight:UIFont = UIFont(name: "HelveticaNeue-UltraLight", size: 12)! var fontBold:UIFont = UIFont(name: "HelveticaNeue-Bold", size: 12)! tabBarItem0.image = unselectedImage0 tabBarItem0.selectedImage = selectedImage0 tabBarItem0.title = "Overview" tabBarItem0.setTitleTextAttributes( [ NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: fontLight ], forState: .Normal) tabBarItem0.setTitleTextAttributes( [ NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: fontBold ], forState: UIControlState.Selected)
-
FedeH over 8 yearshad you found the solution? I'm having the same issue
-
-
Lucas Huang almost 9 yearsHe is asking why the appearance did not change. Not asking how to do it.
-
rmp almost 9 yearsYes, I know that is what he is asking. I believe the reason is that it is not being set correctly.
-
Lucas Huang almost 9 yearsBut the
appearance
is set for the whole app, he probably just wants to set it in this particular case I assume? I think last two lines of codes are correct, it's just not changing to the correct state. Any ideas? @rmp -
rmp almost 9 yearsPer the docs: "In iOS v5.0 and later, you can customize the appearance of tab bars by setting item label text attributes using appearance selectors declared by UIBarItem. "
-
Lucas Huang almost 9 yearsYes, that's correct. But that will apply for every single
UIBarItem
. And I don't say you are wrong. It's just the last two lines of codes are correct as well. The problem is he does not know how to change it toSelected
status. @rmp -
rmp almost 9 yearsThe last two lines of code are not correct, if they were the OP's code would work and there would not have been a post. Also nowhere in the OP does is state that it is for a single Tab, just that when a tab is selected. It would seem odd to not apply the bold selected state to all tabs. Let's just agree to disagree as this is not constructive.
-
Thomas Kremmel almost 9 years
setItems
is setting the items to the tabbar and is used when you want to add, remove or reorder items in the tabbar. This has nothing to do, at least for my understanding, with the select state: goo.gl/LfEIKH -
Thomas Kremmel almost 9 yearsI think both of your answers are not correct ;-) The docs say "you can customize the title’s text attributes using setTitleTextAttributes:forState:, either for a single item, or for all items by using the appearance proxy " . Thus setting it for a single item as I do is fine. goo.gl/oX5KW4
-
Thomas Kremmel almost 9 yearsI even tried it using the
appearance
proxy fromUIBarItem
. Same effect -> no result. I start to consider this to be a Simulator bug. Will try it on real hardware.UIBarItem.appearance().setTitleTextAttributes( [ NSForegroundColorAttributeName: UIColor.whiteColor(),NSFontAttributeName: fontBold], forState: UIControlState.Selected)
-
Lucas Huang almost 9 yearsI just update the answer. You should assign to the
selectedItem
property ofUITabBar
. @ThomasKremmel -
AydinAngouti over 7 yearsThis doesn't change the font for me for
.selected
state. -
damjandd almost 6 yearsDoesn't work properly on iOS 11.4, states getting mixed up.
-
otolock about 3 yearsHi @HapiNguyen! Can you please edit your post to explain why/how your solution answers the OPs question?
-
HapiNguyen about 3 yearsHi @otolock, yes sure, I hope that is clear enough.