0

Swift 5, Xcode 10.2

I want to display 2 lines of text in the UINavigationBar, that's why I'm using a UILabel:

@IBOutlet weak var navigationBar: UINavigationItem!

override func viewDidLoad() {
    let labeltext = NSMutableAttributedString.init(string: "Text in line 1\n(Line 2)")
    labeltext.setAttributes([NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14)],range: NSRange(location: labeltext.length-8, length: 8))
    let label = UILabel()
    label.backgroundColor = .clear
    label.numberOfLines = 2
    label.font = UIFont.boldSystemFont(ofSize: 17.0)
    label.textAlignment = .center
    label.textColor = .black
    label.attributedText = labeltext
    navigationBar.titleView = label
}

In portrait orientation it looks like this:

enter image description here

On smaller devices the text is cut off in landscape (it's fine on iPhone Xs Max and iPad):

enter image description here

I tried to extend UINavigationBar as suggested here:

extension UINavigationBar {
    open override func sizeThatFits(_ size: CGSize) -> CGSize {
        let portraitSize = CGSize(width: UIScreen.main.bounds.width, height: 44)
        return portraitSize
    }
}

... but didn't change anything and print("Navigationbar height: \(navigationController!.navigationBar.frame.height)") always prints "44", no matter what the orientation it is and what device I use (even on iPhone X).

Adding an observer as suggested here also didn't help.

How do I fix this to display 2 lines of code while not breaking it for bigger devices/devices with a notch?

Neph
  • 1,823
  • 2
  • 31
  • 69
  • Maybe you shall write code on device changed orientation ... or condition for UIDevice.current.orientation – ares777 Jun 26 '19 at 14:13
  • How would that help me make it display 2 lines in landscape? `navigationController!.navigationBar.frame.height` gives the same result for both orientations and the extension should take care of the height in landscape but it doesn't. – Neph Jun 26 '19 at 14:29

1 Answers1

0

I didn't find a way to make the UINavigationBar display two lines of text or increase its height (the extension I posted in the question didn't do anything). Instead I'm now using this code to change the label depending on the device and device orientation:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if (UIDevice.current.orientation == .landscapeLeft || UIDevice.current.orientation == .landscapeRight) && UIDevice.current.userInterfaceIdiom == .phone {
        //1 line: iPhone & horizontal (the NavigationBar on iPads is tall enought to display 2 lines!)
        navigationBar.titleView = labelLandscape!
    } else {
        //2 lines: Vertical (device doesn't matter)
        navigationBar.titleView = labelPortrait!
    }
}

Example label:

//let labelTextPortrait = NSMutableAttributedString.init(string: "Text in line 1\n(Line 2)")
let labelTextLandscape = NSMutableAttributedString.init(string: "Text in line 1 (Line 2)")
labelTextLandscape.setAttributes([NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14)],range: NSRange(location: labeltextQuer.length-8, length: 8))
//Text size of "(Line 2)" is 8, the remaining text uses 14

var labelLandscape = UILabel()
labelLandscape!.backgroundColor = .clear
labelLandscape!.numberOfLines = 1 //labelPortrait!.numberOfLines = 2
labelLandscape!.font = UIFont.boldSystemFont(ofSize: 17.0)
labelLandscape!.textAlignment = .center
labelLandscape!.textColor = .black
labelLandscape!.attributedText = labelTextLandscape
labelLandscape!.lineBreakMode = .byWordWrapping //important, so it doesn't truncate mid-text!
Neph
  • 1,823
  • 2
  • 31
  • 69