iOS: Update UINavigationBar Title on Scroll

Apple introduced large navigation bar titles in iOS 11 with the prefersLargeTitles property. When this property is set true then the screens navigation title will be displayed prominently and on scrolling will reduce to a compact display.

Files app with large title
Files app with compact title

The “prefers” in the property name means on smaller devices the large title will be pre-scrolled and not visible. This is a common design in iPhone apps, but doesn’t support multiline text. This post shows how to achieve a similar effect in UIKit, using UITableView and TableHeaderView, that supports multiline text using AutoLayout.

There a several variables required to track the location of the TableHeaderView as it scrolls, the first being the startingOffset. This value is available when the screen appears as contentOffset.y on the UITableView.

Capture the startingOffset

The startingOffset is determined by how the UITableView is constrained to the screen edges e.g. if the UITableView is pinned to the safe area layout guides, then startingOffset will be zero, but if the UITableView is pinned to the screens top edge, then the startingOffset needs to account for the StatusBar height and the NavigationBar height.

The next variable is the currentOffset which is available as contentOffset.y on the ScrollView.

Set title when TableHeaderView has scrolled

The UITableViewDelegate protocol inherits from UIScrollViewDelegate, so this function can be implemented to track the scrolling of UITableView. The currentOffset represents how far and in what direction the UITableView is scrolling.

The UINavigationBar title property can be updated when the currentOffset has moved beyond the height of the TableHeaderView. Checking for nil ensures the title is only set when needed.

The final step is the logic to determine when the TableHeaderView has scrolled up and is no longer visible or has scrolled down and is again visible.

Determine how far the TableHeaderView has scrolled

The startingOffset, currentOffset and height of the TableHeaderView are used to determine when the bottom of the TableHeaderView is aligned with the bottom of the NavigationBar.