1

Problem

A navigation bar animates as it hides on scroll (hidesBarsOnSwipe). If there is a table on the page with a section header, the section header will stick to the top of the view and follow the user as they scroll. When using these two together, there is a gap between the section header and the navigation bar when the navigation bar is hiding, showing the background table cells. I would expect the section header to follow the navigation bar as it hides without a gap.

Using a section header is not strictly necessary for my issue. I'd simply like a bar that sticks to the top of the screen and follows the user as they scroll.

I've tried alternative approaches to the example posted below, which uses a UITableViewController. Adjusting the insets causes the section header to slip under the status bar. Using a UIViewController containing a static UIView (for the section header) and UITableView causes the same issue.

What would be an appropriate solution for this issue?

Example

The status bar's background is gray and the section header's background is red to better highlight the gap between the navigation bar and the section header. As the table is slowly scrolled down, the yellow table cells peeking through the gap become apparent. After the navigation bar is hidden, the section header resets on the status bar as expected.

Scrolling down to hide navigation bar causes gap between section header and hiding navigation bar.

View controller used for the above animation:

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Color status bar background.
        let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
        if statusBar.responds(to: #selector(setter: UIView.backgroundColor)) {
            statusBar.backgroundColor = .lightGray
        }
        UIApplication.shared.statusBarStyle = .default
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
    }

    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view = UIView()
        view.backgroundColor = .red
        return view
    }
}

Update 1

Removing the background color from the status bar does not resolve the issue I am seeing. The GIF below shows the behavior with the status bar in its original, transparent state.

Scrolling down to hide navigation bar causes gap between section header and hiding navigation bar.

TLYShyNavBar has a GIF of the behavior I’d like to implement (added below). This project is not maintained and does not work without additional manipulation but has a good example of what I would expect the behavior to look like.

TLYShyNavBar stick header under hiding navigation bar

Update 2

I’m understanding that this behavior is not an error/issue but as Apple prefers it. Coloring the background of the View is an option (see answer below). There are two ways to go about that for this situation:

  1. Color the background to match the navigation bar and remove the navigation bar’s shadow to make the view seamless.

    self.navigationController?.navigationBar.shadowImage = UIImage() self.navigationController?.navigationBar.isTranslucent = false

    Navigation bar color used for status bar background.

  2. Color the background to match the red bar.

    Red bar color used for status bar background color.

Unfortunately, this method masks the gap instead of removing it. It makes one of the bars appear to distort in shape during their animation until they've completed their transition in both cases.

Brittany
  • 96
  • 1
  • 9
  • @matt Removing the background color of my status bar does not resolve the issue. I've added more details to my question in an update. – Brittany Mar 22 '18 at 18:42

1 Answers1

1

The problem is that a table view does not work well fullscreen when there is a status bar, because the cells come up behind the status bar but the section headers do not. So don't do that.

To use a table view controller to work without a navigation bar but with the status bar showing, configure the table view controller as an embedded (custom child) view controller so that you are in charge of the table view's position. Pin the table view top to the safe area top.

That gives the configuration you are after:

enter image description here

The status bar is clear, and the parent view controller's view is visible behind it. The table view itself, along with its section headers and cells, stops at the bottom of the status bar; the cells do not come up behind the status bar. Thus we don't get the mismatch seen in your illustrations.

Here's a gif showing that the result is coherent:

enter image description here

I've colored the nav bar and the main view differently so you can distinguish them, but imagine they were exactly the same color — then this would be totally coherent.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • However, note that in the TLYShyNavBar screencast you showed, I'm not persuaded that the thing on top is a section header; maybe it is yet another view, above the table view. – matt Mar 22 '18 at 20:21
  • I do think this could be a solution for someone but isn’t quite what I was hoping for since it skews either the nav bar or the view under the bar. And yes, the ShyNavBar library uses a `UIView`, which is an alternative that I am okay with. – Brittany Mar 23 '18 at 02:35
  • I had trouble while implementing this to get the navigation bar to return after it hid, but only when the table view was tied to the safe area instead of the super view. This question appears to have been asked [here](https://stackoverflow.com/q/26524395/3961582) and [here](https://stackoverflow.com/q/36511568/3961582) though. – Brittany Mar 23 '18 at 02:41
  • Do you want to delete your question? It's okay with me. – matt Mar 23 '18 at 02:45