You are currently viewing The Large Title UINavigationBar Glitches and How to Fix Them

The Large Title UINavigationBar Glitches and How to Fix Them

Recently I have been requested by my client to add a large title navigation bar into their app’s main screen, on top of that the large title should automatically collapse when users start scrolling.

Large title navigation bar in iOS 13
Large title navigation bar

I think to myself: how hard could this be? It is just a native iOS component, I should be able to get this done in no time!

Unfortunately, I was wrong.

In this article, I would like to share with you the UI and animation glitches that caught me off guard, and most importantly how I manage to fix them.

Before we get started, There are 2 things you should be aware of:

  1. The glitches that I am about to show you only happened in a UIViewController with a scrollable view (UITableView, UICollectionView or UIScrollView) as a subview. If you are using an UITableViewController or UICollectionViewController, you won’t have to worry about all these glitches.
  2. Throughout the article, I will be using UICollectionView as an example. However, you can apply the same concept to UITableView and UIScrollView as well.

With all that being said, let’s begin!


The Unwanted Snap and Drag Behavior

The first UI glitch that I would like to show you is this:

UINavigationBar with unnatural snapping and navigation bar not expanding while dragging
Unnatural snapping and navigation bar not expanding when dragged

As seen from the above animated GIF, the navigation bar has an unnatural snapping behavior when transitioning from large title to small title. Furthermore, the large title navigation bar does not expand its height when I start dragging downward, causing the title to overlap with the collection view (the yellow color area).

If you are facing the same problem as mine, most probably you and I are having the same auto layout configuration as shown below.

Top constraint aligned to the view controller's top safe area
Top constraint aligned to the view controller’s top safe area

As you can see, the collection view’s top constraint is aligned to the view controller’s top safe area layout guide and that is the root cause of the unwanted behaviors.

In order to solve the problem, all you need to do is to make the collection view’s top constraint align to the top of the view controller’s view.

Align top constraint to the top of the view controller's view
Align top constraint to the top of the view controller’s view

Here’s how you can do it using code:

self.view.addSubview(collectionView)
collectionView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    collectionView.topAnchor.constraint(equalTo: self.view.topAnchor),
    ...
    ...
    ...
])

With this simple change, you should be able to fix the unwanted snap and drag behavior.


Large Title Navigation Bar Not Collapsing

Let’s say you have set up all the auto layout constraints correctly, but when you start scrolling the collection view, the large title navigation bar does not collapse.

Large title navigation bar not collapsing in iOS
Large title navigation bar not collapsing

What should you do?

Based on my investigation, in order for the large title navigation bar to work correctly, the collection view must be the first subview in the view controller’s z-axis.

Let’s say you have a view controller with only 2 subviews — a collection view and an activity indicator. If the activity indicator is located behind the collection view, the navigation bar will not collapse.

Therefore, to fix this glitch, just make sure that there are no other views behind the collection view, then you are good to go.

No other views exist behind the collection view
No other views exist behind the collection view

Do note that if the collection view is inside a container view, as long as the container view is the first subview in the view controller’s z-axis, everything should work correctly as well.


Large Title Navigation Bar with UIRefreshControl

Currently, there are 2 ways to add a UIRefreshControl to a collection view. The first way is the standard way, where you directly assign a refresh control to the collection view.

let refreshControl = UIRefreshControl()
collectionView.refreshControl = refreshControl

Another less-standard way is to add the refresh control as a subview to the collection view.

let refreshControl = UIRefreshControl()
collectionView.addSubview(refreshControl)

Surprisingly, if the large title is enabled, both of these ways will result in different pull-to-refresh behavior. Let me show you what I mean.

If you are using the standard way, the refresh control will animate on top of the large title.

Refresh control animate on top of the large title navigation bar.
Refresh control animate on top of the large title

Whereas when using the less-standard way, the refresh control will animate below the large title.

Refresh control animate at bottom of the large title navigation bar.
Refresh control animate on top of the large title

Is this an animation glitch? I am not sure 😅. But still, I think this is an interesting discovery that is worth sharing.

Personally, I would suggest everyone to use the standard way because it is less hacky, which in other words means it is more future proof. Furthermore, the pull-to-refresh animation does look and feel more natural.


Bonus Trick: Styling the Large Title Navigation Bar

If you are using the large title navigation bar, most probably you will want to adjust its styling to suit your needs. This is where the UINavigationBarAppearance APIs introduced in iOS 13 comes in handy.

For example, you can use the following code snippet to customize a specific view controller’s navigation bar font and background color.

let appearance = UINavigationBarAppearance()

// Set background color
appearance.backgroundColor = .systemTeal

// Set font
appearance.largeTitleTextAttributes = [
    NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 30)
]
appearance.titleTextAttributes = [
    NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 15)
]

// Apply the appearance
self.navigationController?.navigationBar.scrollEdgeAppearance = appearance
self.navigationController?.navigationBar.compactAppearance = appearance
self.navigationController?.navigationBar.standardAppearance = appearance

If you would like to change the navigation bar styling thoughtout the entire app, you can add the following code snippet to the application(_:didFinishLaunchingWithOptions:) delegate method.

let appearance = UINavigationBarAppearance()
appearance.backgroundColor = . systemTeal

appearance.largeTitleTextAttributes = [
    NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 30)
]
appearance.titleTextAttributes = [
    NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 15)
]

UINavigationBar.appearance().scrollEdgeAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().standardAppearance = appearance

Wrapping Up

Apple makes enabling the large title navigation bar extremely easy. However, getting it right is a little bit tricky. Therefore, next time if you bump into any unexpected glitches when using a large title navigation bar, remember to check the following:

  1. The scrollable content top constraint must align to the top of the view controller’s view.
  2. The scrollable content (or its container) must be the first subview in the view controller’s z-axis.
  3. If you are using a UIRefreshControl, make sure to use the standard way to assign it to the scrollable content.

Lastly, if the screen that you create is not complicated, you can always use the UITableViewController and UICollectionViewController to avoid any of these glitches.


If you enjoy reading this article, feel free to check out my other iOS development related articles. You can also follow me on Twitter, and subscribe to my monthly newsletter.

Thanks for reading. 👨🏻‍💻


👋🏻 Hey!

While you’re still here, why not check out some of my favorite Mac tools on Setapp? They will definitely help improve your day-to-day productivity. Additionally, doing so will also help support my work.

  • Bartender: Superpower your menu bar and take full control over your menu bar items.
  • CleanShot X: The best screen capture app I’ve ever used.
  • PixelSnap: Measure on-screen elements with ease and precision.
  • iStat Menus: Track CPU, GPU, sensors, and more, all in one convenient tool.