20

I've been trying the following in order to get the title of a navigation bar left aligned:

In the AppDelegate.swift file:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.


    UINavigationBar.appearance().barTintColor = UIColor.red
    UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName:
        UIColor.white]
    return true
}

In a TableViewController.swift file:

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.navigationController?.navigationBar.topItem?.title = "Home"
    }

but nothing I find solves the problem. I also tried the following that I found on here which does not show anything:

in the AppDelegate.swift file:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.


    UINavigationBar.appearance().barTintColor = UIColor.red
    UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName:
        UIColor.white]
let lbNavTitle = UILabel (frame: CGRect(x: 0, y: 40, width: 320, height: 40))
    lbNavTitle.center = CGPoint(x: 160, y: 285)
    lbNavTitle.textAlignment = .left
    lbNavTitle.text = "Home"
    self.navigationItem.titleView = lbNavTitle

In a TableViewController.swift file:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.navigationController?.navigationBar.topItem?.title = "Home"
    let lbNavTitle = UILabel (frame: CGRect(x: 0, y: 0, width: 320, height: 40))
    lbNavTitle.backgroundColor = UIColor.red
    lbNavTitle.textColor = UIColor.black
    lbNavTitle.numberOfLines = 0
    lbNavTitle.center = CGPoint(x: 0, y: 0)
    lbNavTitle.textAlignment = .left
    lbNavTitle.text = "Home"

    let string = NSMutableAttributedString ("Title/nSubTitle")

    self.navigationItem.titleView = lbNavTitle
}
D4ttatraya
  • 3,344
  • 1
  • 28
  • 50
Shamar Yarde
  • 747
  • 1
  • 7
  • 19

5 Answers5

54
let label = UILabel()
label.textColor = UIColor.white
label.text = "TCO_choose_reminder".localized;
self.navigationItem.leftBarButtonItem = UIBarButtonItem.init(customView: label)

I init a UIBarButtonItem with the constructor that gets a UIView and set my desired label as parameter to get the following.

enter image description here

Edit:

If you do not want the back button to be removed. Set the following flag.

self.navigationItem.leftItemsSupplementBackButton = true

Keep in mind that having a label + Back button (with title) would not look cool.In this case I replace the default back button with an arrow asset.

Ilker Baltaci
  • 11,644
  • 6
  • 63
  • 79
13

You can use the navigationItems titleView to add a UILabel with left alignment and then set its frame using auto layout like this:

let label = UILabel()
label.text = "Title Label"
label.textAlignment = .left
self.navigationItem.titleView = label
label.translatesAutoresizingMaskIntoConstraints = false
label.superview?.addConstraint(NSLayoutConstraint(item: label, attribute: .centerX, relatedBy: .equal, toItem: label.superview, attribute: .centerX, multiplier: 1, constant: 0))
label.superview?.addConstraint(NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal, toItem: label.superview, attribute: .width, multiplier: 1, constant: 0))
label.superview?.addConstraint(NSLayoutConstraint(item: label, attribute: .centerY, relatedBy: .equal, toItem: label.superview, attribute: .centerY, multiplier: 1, constant: 0))
label.superview?.addConstraint(NSLayoutConstraint(item: label, attribute: .height, relatedBy: .equal, toItem: label.superview, attribute: .height, multiplier: 1, constant: 0))
Upholder Of Truth
  • 4,643
  • 2
  • 13
  • 23
  • Thanks. This works. The line: self.navigationController?.navigationItem.title = label.text needs to be added to ensure you got the desired result. – Shamar Yarde Jun 12 '17 at 20:26
  • if I Do this app is crashing by saying 'Cannot modify constraints for UINavigationBar managed by a controller. I tried on ViewDidLoad, ViewWillAppear & viewDidLayoutSubviews – Neha Nov 10 '17 at 05:35
  • @Neha that could be many things. I would suggest asking your own question which would then allow you to add details of your code, etc. – Upholder Of Truth Dec 26 '17 at 22:08
  • @Neha I also experienced that error. I'm too lazy to check out why. So here is my solution . Instead of adding constraints , I added this one to make the frame of label equal to the size of superview: if let titleView = label.superview { label.frame = titleView.frame } – Andrew James Ramirez Mar 01 '18 at 09:11
  • 2
    This didn't work for me, https://stackoverflow.com/a/42430844/2764966 worked for me. – ViruMax Jun 28 '18 at 06:54
  • You are right my approach no longer appears to work properly, not sure why. However the other approach uses calculated values (width in particular) that will be incorrect if there is any size change such as when you rotate the device so you will need to take that into account – Upholder Of Truth Jun 28 '18 at 07:24
  • This gets the label on top of the left item. – Nicolas Miari Sep 06 '19 at 10:12
  • This approach works for me as of Oct 2020 (Xcode 12 / iOS 14). I only used two attributes: .leftMargin and .rightMargin. Make sure you place navigationItem.titleView = label before adding constraints. – Denis Bystruev Oct 09 '20 at 06:20
  • This answer does not work for me. Also, the comment by Denis Bystruev doesn't provide enough info about how to use .leftMargin and .rightMargin. – Ted Henry Dec 22 '20 at 02:50
  • It seems that `label.superview?` is `nil`. – Ted Henry Dec 22 '20 at 03:00
  • Did you set the navigation items title view to be the label before setting the constraints otherwise it will fail. – Upholder Of Truth Dec 22 '20 at 09:57
5

Well, if you'd like to use large title, then it is left aligned by defaut.

For whole navigation hierarchy.

navigationController?.navigationBar.prefersLargeTitles = true

For 1 viewController

navigationItem.largeTitleDisplayMode = .always
Zhou Haibo
  • 1,681
  • 1
  • 12
  • 32
  • i suspect this is the 'official' way to do this even if it's not very clear from the docs or the api naming – glotcha Jul 01 '22 at 01:14
3

This works for me (iOS 13+):

    let offset = UIOffset(horizontal: -CGFloat.greatestFiniteMagnitude, vertical: 0)
    navigationController?.navigationBar.standardAppearance.titlePositionAdjustment = offset
    navigationController?.navigationBar.scrollEdgeAppearance?.titlePositionAdjustment = offset
    navigationController?.navigationBar.compactAppearance?.titlePositionAdjustment = offset
Leszek Szary
  • 9,763
  • 4
  • 55
  • 62
1

If u want a simple left aligned text that covers the entire titleView area heres my solution guys!.

func setLeftAlignTitleView(font: UIFont, text: String, textColor: UIColor) {
    guard let navFrame = navigationController?.navigationBar.frame else{
        return
    }
    
    let parentView = UIView(frame: CGRect(x: 0, y: 0, width: navFrame.width*3, height: navFrame.height))
    self.navigationItem.titleView = parentView
    
    let label = UILabel(frame: .init(x: parentView.frame.minX, y: parentView.frame.minY, width: parentView.frame.width, height: parentView.frame.height))
    label.backgroundColor = .clear
    label.numberOfLines = 2
    label.font = font
    label.textAlignment = .left
    label.textColor = textColor
    label.text = text
    
    parentView.addSubview(label)
}