Navigation bar titleView alignment

2020-06-17 04:22发布

问题:

I want my navigation bar to show two things in the middle. One them is going to be List name, and the other one will be name of users. User names will be placed under list name. What i have done so far is, i created two label and one superview programatically and set the titleView of navigationItem.

override func viewDidLoad() {
        super.viewDidLoad()
        var rectForView = CGRect(x: 0, y: 0, width: 190, height: 176)
        var viewForTitle = UIView(frame: rectForView)

        var rectForNameLabel = CGRect(x: 0, y: 63, width: 190, height: 30)
        var listNameLabel = UILabel(frame: rectForNameLabel)
        listNameLabel.text = "Name of the List...."
        listNameLabel.textAlignment = NSTextAlignment.Center
        listNameLabel.font = UIFont(name: "HelveticaNeue-Bold", size: 15)

        var rectForListLabel = CGRect(x: 0, y: 93, width: 190, height: 20)
        var usersOfListLabel = UILabel(frame: rectForListLabel)
        usersOfListLabel.text = "some Users...."
        usersOfListLabel.textAlignment = NSTextAlignment.Center
        usersOfListLabel.font = UIFont(name: "HelveticaNeue", size: 10)

        viewForTitle.addSubview(listNameLabel)
        viewForTitle.addSubview(usersOfListLabel)


        self.navigationItem.titleView = viewForTitle

The thing is, I'm picking width randomly, which leads to alignment problems in different devices. How to achieve middle alignment in my case?

回答1:

The thing is, navigation titleView always try to center your view. The reason that the title you see off-center in a smaller screen is that, the width of your custom titleView has gone beyond the maxmium width of titleView.

If you set the value to 160, you will see it centered for the second situation.

General Solution

If you want to adapt title width to different devices, there are a few approaches that may help you solve the problem.

  1. Set different width based on different screen width. For example, when screen width is 320, set it no more than 160. If larger than 320, assign value based on different screen size. This is not an elegant solution, but pretty much straightforward without banging your head into setting and trying complicated constraints.

  2. Calculate the actual width of titleView. The width of titleView is determined by navigation bar width minus left and right barbuttonitem. Something like

TitleViewWidth = Navigation width - leftbarbuttonitem.width +/- rightbarbuttonitem.width - someConstant

You need a little bit experiment for finding the appropriate constant that fits this formula.

  1. Create a xib file for this titleView, set up constraints more flexibly than claim a fixed width. Load view from xib and then assign to titleView. This may cost longer time to tune it to work.

Edit

I think of another way that may be easier for you if you are new to this.

In the storyboard, find and drop a view to this view controller's navigation bar titleView area.

Expand however long you want the view to be.

Drop two labels to that view, and set the leading and trailing and height and vertical constraints.

How it looks on storyboard

How it runs on 4S



回答2:

Approach:

  • titleView is always centred
  • So set your custom view's width to match that of the navigationBar (width -40)

Code

private func setupNavigationItems() {

    let label = UILabel()

    label.translatesAutoresizingMaskIntoConstraints = false

    label.text = "aaaaa"
    label.backgroundColor = .green

    label.textAlignment = .left

    navigationItem.titleView = label

    if let navigationBar = navigationController?.navigationBar {

        label.widthAnchor.constraint(equalTo: navigationBar.widthAnchor, constant: -40).isActive = true
    }
}