14

I have a ViewController and a DetailViewController, in the ViewDidLoad of the ViewController I set the following code, the purpose is to make the ViewController always use the large title

self.navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always

In the ViewDidLoad of the DetailViewController I set the following code, the purpose is to make the DetailViewController not use the large title

navigationItem.largeTitleDisplayMode = .never

When I return from DetailViewController to ViewController, the small title is displayed instead of the large title in ViewController. This code is correct in iOS12 and iOS13. How to make the ViewController always display the large title on iOS14?

Currently using Xcode12 from the App Store

BaQiWL
  • 417
  • 5
  • 14

5 Answers5

15

For iOS 14, need to add sizeToFit function. Below code always work.

navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.sizeToFit()
Symon
  • 633
  • 6
  • 15
  • 2
    Its not working for me. I just called this on VC-1's didload and willappear. – Lal Krishna Feb 24 '21 at 12:10
  • This did work but showing some glitches while changing small navigation title to large navigation titlw when coming back from other viewcontroller who have small navbar. It shows no animation in transition. Could you please suggest something on this. – Ashwini Salunkhe Sep 06 '21 at 14:45
8

At last solved the issue.

Edge case:

If you're using large title, and you have multiple scroll views on the same view controller. Navigation bar will listen to scroll actions on the subviews (immediate subview) of kind UIScrollView.

Solution

You have to prevent current view controller's large title collapsing feature.

Its same concept as @BaQiWL mentioned. But not just adding view.addSubview(UIView()) will solve this issue, if you're using storyboard.

To do this you have to add view as Viewcontroller's first subview. (view.sendSubviewToBack does the trick).

// Call this method on `viewDidLoad`
private func preventLargeTitleCollapsing() {
    let dummyView = UIView()
    view.addSubview(dummyView)
    view.sendSubviewToBack(dummyView)
}

OR via Storyboard:

enter image description here

Lal Krishna
  • 15,485
  • 6
  • 64
  • 84
2

If the scene is based on a UITableView, you need to scroll it.

override func viewDidLoad() {
    super.viewDidLoad()
    
    // enough for the first scene.
    navigationController?.navigationBar.prefersLargeTitles = true
    tableView.setContentOffset(CGPoint(x: 0, y: -1), animated: false) // hack for modal prefersLargeTitles
    
}

always present largeTitleDisplayMode for modal view controller

Sergey Sergeyev
  • 776
  • 8
  • 12
1

My ViewController has a UIPageViewController, UIPageViewController has a UIScrollView, this is the key point.

This link explains and solves the problem

add view.addSubview(UIView()) in ViewController's viewDidLoad

BaQiWL
  • 417
  • 5
  • 14
  • I do have the same case. But adding subview not resolved my issue. Tried adding to ViewCOntrollerA as well as, viewcontroller inside pageviewcontroller. – Lal Krishna Mar 01 '21 at 08:02
-3

Use my extension:

extension UIViewController {
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
if #available(iOS 13.0, *) {
    let navBarAppearance = UINavigationBarAppearance()
    navBarAppearance.configureWithOpaqueBackground()
    navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
    navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
    navBarAppearance.backgroundColor = backgoundColor

    navigationController?.navigationBar.standardAppearance = navBarAppearance
    navigationController?.navigationBar.compactAppearance = navBarAppearance
    navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance

    navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
    navigationController?.navigationBar.isTranslucent = false
    navigationController?.navigationBar.tintColor = tintColor
    navigationItem.title = title

} else {
    // Fallback on earlier versions
    navigationController?.navigationBar.barTintColor = backgoundColor
    navigationController?.navigationBar.tintColor = tintColor
    navigationController?.navigationBar.isTranslucent = false
    navigationItem.title = title
  }
 }
}

set your navigation bar in viewWillAppear:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    configureNavigationBar(largeTitleColor: .white, backgoundColor: .yourColor, tintColor: .white, title: "YourTitle", preferredLargeTitle: true)
}

now cal the function that present your detail controller:

@objc func DetailController(){
    let controller = DetailViewController()
    controller.navigationItem.largeTitleDisplayMode = .never
    navigationController?.pushViewController(controller, animated: true)
}

This is the result:

enter image description here

enter image description here

Fabio
  • 5,432
  • 4
  • 22
  • 24
  • Thanks, but still not working on Xcode12 and iOS14,are you using Xcode12 and iOS14? – BaQiWL Sep 23 '20 at 07:38
  • Yes, and it works fine.... look at my new pic answer – Fabio Sep 23 '20 at 07:45
  • Are you using my extension? Delete all your nav bar settings and use the extension and it works like a charm... – Fabio Sep 23 '20 at 07:59
  • Thank you very much, I tested your code in a new project, there is no problem, It should be a problem with the code under my old project – BaQiWL Sep 23 '20 at 08:58
  • @BaQiWL Have a nice day :) – Fabio Sep 23 '20 at 09:07
  • Its not working for Xcode 12.2 and iOS 14.1 – Symon Dec 15 '20 at 01:44
  • @Symon I try it now and it works like a charme... Probably you don't embed your controller in a navigation controller... Before writing any comments that might put future users out of the road, try checking all options .... – Fabio Dec 16 '20 at 06:33