Prashant Tukadiya
Prashant Tukadiya

Reputation: 16416

How to set custom title view to center of navigation bar

I am trying to add custom view (Label) as title view of navigation item.

but it is not appearing in centre

func setupNavigationMultilineTitle(title:String) {
        let autoscrollLabel = EFAutoScrollLabel()
        autoscrollLabel.text =  title
        autoscrollLabel.textAlignment = .center
        autoscrollLabel.backgroundColor = .red

        autoscrollLabel.font = AppTheme.Fonts.font(type: .Medium, size: 15)
        autoscrollLabel.textColor = AppTheme.Colors.ColorsOfApp.header_color.color
        autoscrollLabel.frame = CGRect(x: 0, y: 0, width:((self.navigationController?.navigationBar.frame.size.width ?? 0) - (self.navigationItem.leftBarButtonItem?.customView?.frame.width ?? 0) * 2) , height: 40)
        self.navigationItem.titleView = autoscrollLabel

    }

I have tried to use deduct width of custom view to show it in center but unfortunately it is not working.

I have also tried to get self.navigationItem.leftBarButtonItem.width but it returns 0. I confirmed that there is leftBarbutton item with po self.navigationItem.leftBarButtonItem

EDIT

This solves issue

    autoscrollLabel.frame = CGRect(x: self.view.center.x - 125, y: 0, width: 250 , height: 40)

But I need dynamic solution

enter image description here

Any help would be appreciated

Upvotes: 1

Views: 3008

Answers (3)

Robihamanto
Robihamanto

Reputation: 43

Add my version code based on @dahiya_boy answers. In my case, I have a custom button that has a more 30-width size. So, rather than multiply it by 30, I find a max from left and right items to find the max. Below is the code:

func setCenterTitle(_ title: String) {
        let navWidth = (navigationController?.navigationBar.frame.width).orZero
        let leftItemsWidth = leftBarButtonItems.orEmptyArray.reduce(0) {
            $0 + ($1.customView?.frame.width).orZero
        }
        let rightItemsWidth = rightBarButtonItems.orEmptyArray.reduce(0) {
            $0 + ($1.customView?.frame.width).orZero
        }
        let maxItemsWidth = max(leftItemsWidth, rightItemsWidth)
        let padding: CGFloat = 40
        let labelWidth = navWidth - (maxItemsWidth * 2) - padding
        let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: labelWidth, height: 40))
        titleLabel.text = title
        titleLabel.textAlignment = .center
        titleLabel.font = UIFont.boldSystemFont(ofSize: 16)
        self.titleView = titleLabel
    }

Upvotes: 0

dahiya_boy
dahiya_boy

Reputation: 9503

I debugged your scenario, hope it helps you and other developers,

When we assign tittleView width by calculating the space left after subtracting space of items, margins, padding etc then iOS calculate titleView X from the right side i.e. titleview.x = rightItem.x - width and we are expecting it like titleview.x = navbar.width/2 - width/2.

Please look below sample test cases.


Calculate width

let maxItemOnEitherSide = max(arrLeftItems.count, arrRightItems.count)
let widthOfItem : CGFloat = 30.0
let pading : CGFloat = 40

let aWidth : CGFloat = (self.navigationController?.navigationBar.frame.width)! - CGFloat(maxItemOnEitherSide) * widthOfItem * 2.0 - pading

let lblNavTitle = UILabel(frame: CGRect(x: 0, y: 0,
                                        width: aWidth,
                                        height: 40))

Case 1 : arrLeftItems.count = 1 and arrRightItems.count = 0.

Output :

enter image description here

Case 2 : arrLeftItems.count = 0 and arrRightItems.count = 1.

enter image description here


Hope above cases clear you out what we are expecting and what we are getting and the calculation that I wrote in first para i.e. titleview.x = rightItem.x - width.

Conclusion :

If rightBarItems have more items than leftBarItems then titleview will be in center, so you wont need to do anything but if leftBarItems have more items than rightBarItems then add blank items in right side to make it balance. It is weird for developers but seems like its the only solution.

Check the final output.

  • View Heirarchy

enter image description here

  • Output

enter image description here

Upvotes: 4

ecco55
ecco55

Reputation: 31

If your navigation Item is part of a UINavigationController you could try self.navigationController?.navigationBar.topItem?.leftBarButtonItem?.width ?? 0.0

Upvotes: 0

Related Questions