Search code examples
iosswiftuinavigationbarstatusbarlarge-title

iOS 11 scroll to top when using large titles doesn't work properly


When using large titles and tapping the status bar to scroll to the top of a UIScrollView or UITableView (probably also UICollectionView, haven't tested this) it always goes a little too far.

I have refresh enabled on my TableView and when tapping the status bar it appears like this and stays that way until I tap the screen.

enter image description here

I have a ScrollView in another ViewController and if I tap the status bar there it also scrolls a little bit too far, making the navigation bar too tall. This also returns to normal when I tap somewhere or scroll a tiny bit.

Normal: enter image description here

After I tapped the status bar: enter image description here

This also only happens when I have large titles activated, using normal titles everything works as it should.

Any ideas how to fix this?

How to recreate:

  1. Create a new project with a navigation controller and a UIViewController with a TableView inside.
  2. Set navigation controller to prefer large titles. Turn translucent off. Set title on UIViewController
  3. Set constraints on TableView to pin to the edges of the ViewController
  4. Create outlet for TableView in the ViewController
  5. Implement delegates and set a number of rows, for example 100
  6. Launch app
  7. Scroll down so the large title becomes a normal title
  8. Tap status bar so the tableView scrolls to the top

Now the title is not at the position it should be, if you now scroll a tiny bit up or down it snaps back to the normal position.

ViewController code:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
    }

}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath)

        return cell
    }

}

Solution

  • Okay so I found why the problem occurs, but not how to fix it in that exact scenario.

    If you're using large titles and a UITableViewController with the navigation bar translucency set to off the problem will occur. When you turn translucent back on the problem goes away.

    If you're using a TableView in a normal UIViewController the problem always occurs.

    Edit

    Turns out setting "extendedLayoutIncludesOpaqueBars = true" fixes the problem if you're using a translucent navigation bar!

    Similar question: UIRefreshControl() in iOS 11 Glitchy effect