8

I've tried many things but impossible to find a way to put the label of a UITabBarItem with a lineNumber customised.0 (i would like to get the title on 2 lines).

Is there a way to do it?

Mr.Kushwaha
  • 491
  • 5
  • 14
Kevin Vacquier
  • 622
  • 6
  • 17
  • you want label in UITabBarItem its mean you also want its touch event (i guess) ? then you can directlly use UIButton with multiple lines. – Er.Gopal Vasani Sep 14 '17 at 13:06
  • The "title label" is not exposed... You will almost certainly need to use a custom tab bar. – DonMag Sep 14 '17 at 13:15

5 Answers5

8

Now it contains two subviews. At 0 it is imageView and at 1 it is label. Now make the height of imageview a bit smaller so that you can give the height of label a bit larger to have multiple lines. Set the property ofnumberoflines of the label to 0 via code.

let viewTabBar = tabBarItem.value(forKey: "view") as? UIView
let imageView = viewTabBar?.subviews[0] as? UIImageView
let label = viewTabBar?.subviews[1] as? UILabel

and now play with this label.

Mr.Kushwaha
  • 491
  • 5
  • 14
Arnav
  • 668
  • 6
  • 14
  • 1
    You should get a medal for that ;) I'm pretty sure your answer will help tons of people ! – Kevin Vacquier Sep 15 '17 at 14:32
  • 2
    note that if you dont have image, the index of UILabel will be 0, I've posted more generic solution below – Bogdan Nov 02 '17 at 10:15
  • 1
    Can you please explain it, what is the value for key 'view'? When I run this code, I'm getting viewTabBar as nil. – Hilaj S L May 29 '19 at 10:53
  • 1
    This is an incomplete answer, with no proof it works. How do you move the image and label upwards, make the tabbar higher, and then account for the two lines? All this does is show how TabBarItems has subviews. It's not an answer. – John Pitts Apr 16 '20 at 02:43
  • @Arnav reference to your answer, possible can I ask question `tabbar item title` related? – Tekhe Dec 11 '20 at 14:47
  • yups...How can I help you @Tekhe – Arnav Dec 16 '20 at 15:25
  • @Arnav Is Multiline tabbar title works on iPhone 8 ? Its working on İPhone X, 11 or pro max series but not on iPhone 8. I have tried your solution as well but no. – Tekhe Dec 17 '20 at 16:27
  • As per John Pitts comment, this doesn't show the details of what needs to be done. See [Was'Siim's more recent answer](https://stackoverflow.com/a/60320339/199364) for a complete solution. – ToolmakerSteve Dec 14 '21 at 21:16
5

More stable solution:

guard let view = tabBarItem?.value(forKey: "view") as? UIView,
        let label = (view.subviews.compactMap{ $0 as? UILabel }).first,
        let imageView = (view.subviews.compactMap{ $0 as? UIImageView }).first else { return }
Nikolay Suvandzhiev
  • 8,465
  • 6
  • 41
  • 47
Bogdan
  • 1,286
  • 9
  • 12
3

This is my solution for that

We need to implement this inside viewwillLayoutSubviews, to update the UI and make it works.

In this example in going to customize my 3rd tab bar item only

override func viewWillLayoutSubviews() {
    // acess to list of tab bar items
    if let items = self.tabBar.items {
        // in each item we have a view where we find 2 subviews imageview and label
        // in this example i would like to change
        // access to item view
        let viewTabBar = items[2].value(forKey: "view") as? UIView
        // access to item subviews : imageview and label
        if viewTabBar.subviews.count == 2 {
            let label = viewTabBar?.subviews[1]as? UILabel
            // here is the customization for my label 2 lines
            label?.numberOfLines = 2
            label?.textAlignment = .center
            label!.text = "tab_point".localized
            // here customisation for image insets top and bottom
            items[2].imageInsets = UIEdgeInsets(top: 8, left: 0, bottom: -5, right: 0)
        }
    }
}

and here is the result enter image description here

Nikolay Suvandzhiev
  • 8,465
  • 6
  • 41
  • 47
Wassim Ben Hssen
  • 519
  • 6
  • 23
1
    tabBar.items?.forEach {
        $0.imageInsets = UIEdgeInsets(top: 8, left: 0, bottom: -15, right: 0)
        
        guard let view = $0.value(forKey: "view") as? UIView,
              let label = (view.subviews.compactMap{ $0 as? UILabel }).first,
              let imageView = (view.subviews.compactMap{ $0 as? UIImageView }).first else { return }
        
        label.numberOfLines = 2
        if CBServerManagerApi.sharedManager().currentUser.type == "Local" {
            label.text = titles[element]
        }
        label.lineBreakMode = .byTruncatingTail
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false  
        NSLayoutConstraint.activate([
        label.heightAnchor.constraint(equalToConstant: 30)
        ])
    }
Pitt
  • 29
  • 3
0

You can not do this with UITabBarItem because it doesn't have property titleView like UINavigationItem.

You can set only string as title and tab image. That's it.

If UITabBarItem had a titleView property then you would have the option to set a label as titleView with numberOfLines set to 0 but here you can only set the title as a string.

HangarRash
  • 7,314
  • 5
  • 5
  • 32
Ketan Parmar
  • 27,092
  • 9
  • 50
  • 75