Skip to content

Instantly share code, notes, and snippets.

@joshavant
Last active December 1, 2015 00:45
Show Gist options
  • Select an option

  • Save joshavant/1538378f00a1b8415dfd to your computer and use it in GitHub Desktop.

Select an option

Save joshavant/1538378f00a1b8415dfd to your computer and use it in GitHub Desktop.
Translucent Bar Bliss: Scroll View Insetting w/ Nav + Tab Bars, in an IB Workflow

Translucent Bar Bliss: Scroll View Insetting w/ Nav + Tab Bars, in an IB Workflow

This document describes how to configure your scroll views in IB, so that their insets are configured to accomodate coverage by UINavigationBar and UITabBar.

A common reason for wanting this is to allow these views to configured as 'translucent', while scroll view content scrolls beneath them.

This guide is broken up into two types of view configurations...

  • Configuration 1: A top-level scroll view, which fills UIViewController's view
  • Configuration 2: A top-level scroll view, which does not fill UIViewController's view

Configuration 1: A top-level scroll view, which fills UIViewController's view

This configuration happens when your UIViewController's view is or contains a single scroll view which fills the entirety the view.

(If your UIViewController is actually a UITableViewController, only follow the IB: UIViewController settings section, and ignore the rest.)

If there are other views in the root of the view hierachy, the scroll view must be at z-index of 0 (that is, it should be the bottommost view).

IB: UIViewController settings:

Enable:

  • Adjusts Scroll View Insets
  • Under Top Bars
  • Under Bottom Bars

IB: UIViewController.view Auto Layout constraints:

Create two constraints by Control-Dragging from the scroll view instance to the UIViewController's view instance in the IB view hierarchy.

Then, holding Option, select these constraints:

  • Top Space to Container Margin
  • Bottom Space to Container Margin

... this yields the following Constraints on the UIViewController's view instance:

  • Bottom Margin Space to: [Scroll View]
  • Top Margin Space to: [Scroll View]

If you don't want the UINavigationBar to cover the top of the scroll view in the IB preview of your view, ignore the last constraint from above, and, instead, create these two constaints:

  • Top Margin Space to: [Scroll View] @ 999 priority
  • Top Margin Space to: [Scroll View], constant: 64, enabled: Remove at build time

...the same can be done to prevent UITabBar coverage by appropriately inverting the parameters and objects of the above steps.


Configuration 2: A top-level scroll view, which does not fill UIViewController's view

This configuration happens when your UIViewController's view contains a scroll view which does not fill the entirety of the view.

A common exammple of this configuration is if you have a header- or footer-like view that your scroll view is pinned to on the top or bottom edge.

The primary point of concern for this configuration is that automaticallyAdjustsScrollViewInsets is arguably broken, and does work as you might expect [1]. Therefore, in these scenarios, insetting will need to be implemented programmatically.

IB: UIViewController settings:

Enable:

  • Under Top Bars
  • Under Bottom Bars

Disable:

  • Adjusts Scroll View Insets

IB: UIViewController.view Auto Layout constraints:

Follow the instructions from Configuration 1.

Code: UIViewController.viewDidLayoutSubviews implementation:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    if let superview = tableView.superview where superview == view {
          let tableViewTopContentInset = max(0, topLayoutGuide.length - CGRectGetMinY(tableView.frame))
          
          let tableViewBottomContentInset = max(0,
              bottomLayoutGuide.length - (CGRectGetHeight(superview.frame) - CGRectGetMaxY(tableView.frame)))
          
          tableView.contentInset = UIEdgeInsets(top: tableViewTopContentInset,
              left: tableView.contentInset.left,
              bottom: tableViewBottomContentInset,
              right: tableView.contentInset.right)
          
          tableView.scrollIndicatorInsets = UIEdgeInsets(top: tableViewTopContentInset,
              left: tableView.scrollIndicatorInsets.left,
              bottom: tableViewBottomContentInset,
              right: tableView.scrollIndicatorInsets.right)
        }
}

[1] More information: https://openradar.appspot.com/23666782

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment