I know that you can set the font, color, font size separately for "big" and "small" headers when using prefersLargeTitles.

But is it possible, with the "LargeTitles" on the navigation controller, to ensure that the "big header" on the "expanded" navigation bar is shown in uppercase characters?

Those. to achieve this effect:

enter image description here

Now for this purpose I use custom Navigation Controller:

class MyNavigationController: UINavigationController { public var titleSaved: String? override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() guard let topItem = navigationBar.topItem else { return } if navigationBar.frame.size.height > 60 { topItem.title = topItem.title?.uppercased() } else { if let titleSaved = titleSaved { topItem.title = titleSaved } else { topItem.title = topItem.title?.applyingTransform(StringTransform(rawValue: "Title"), reverse: false) } } } } 

setting the title from the View Controller:

 class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() navigationController?.navigationBar.prefersLargeTitles = true let title = "Sign In" navigationItem.title = title if let nc = navigationController as? MyNavigationController { nc.titleSaved = title } } } 

This solution works, but when you go from the “big” heading to the “small” one and back, it twitches a bit - it doesn't look very nice ...

    1 answer 1

    Unfortunately, the attributed string does not have such a key to set the register. Yes, and larg title have a rather meager set of settings, probably to look uniform from application to application.

    If you need to change only the register of the title, make your element with a similar behavior, but the necessary features.

    If other advantages are also needed, it is necessary to keep track of the current state and, depending on this, change the title.


    Option with KVO and UILabel as titleView, but I think it will suit you for the task. Result:

    enter image description here

    First we need to find the part responsible for the Large Title and then monitor the changes. Full example:

     class ViewController: UIViewController { var observing: NSKeyValueObservation? override func viewDidLoad() { super.viewDidLoad() configureTitle() } func configureTitle() { //: Настраиваете шрифт/размер как угодно let titleLabel = UILabel() //: - Устанавливаем начальный заголовок как текст кастомного titleView titleLabel.text = navigationItem.title navigationItem.titleView = titleLabel //: - Делаем заголовок большими буквами для Large Title navigationItem.title = navigationItem.title?.uppercased() let largeTitleView = navigationController?.navigationBar.getLargeTitleView() observing = largeTitleView?.observe(\.alpha, options: [.new], changeHandler: { [weak titleLabel] (label, value) in if let alpha = value.newValue { titleLabel?.alpha = alpha.isZero ? 1 : 0 } }) } } extension UINavigationBar { func getLargeTitleView() -> UIView? { for subview in subviews { if String(describing: type(of: subview)) == "_UINavigationBarLargeTitleView" { return subview } } return nil } } 
    • But how can you track the state of “big” now heading or “small” and catch the moment of transition from one state to another? - xhr
    • @xhr updated the answer - VAndrJ
    • What's wrong with KVO? Why is "KVO not offering"? - xhr
    • @xhr KVO is not bad, it is very good. But UIKit doesn't seem to support it, more info: developer.apple.com/library/archive/documentation/General/… . And the fact that while everything works out is a side effect of NSObject and someday it may break. Or maybe not :) - VAndrJ 5:52 pm