Pull to Refresh with iOS 7 style cover image behind Navigation Bar

A very common interface design that we have started seeing with iOS7 apps is having a big cover photo on the top of table views which extends all the way up to the status bar. Here’s an example. However, by default, iOS adds an inset to the scroll views so that the content starts from below the top layout guide. Its easy to put everything back to top, though. All we need is to set the contentInset of tableview to UIEdgeInsetsMake(0, 0, 0, 0).

Lets try to put a refresh control to our tableview now. I like to use a UIViewController instead of a UITableViewController to have more control over the views. Here’s a hack to make the refresh control work with UIViewController.

// Add pull to refresh control.
UITableViewController *tableViewController = [[UITableViewController alloc] init];
tableViewController.tableView = self.tableView;
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(doRefresh) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = self.refreshControl;

Now try pulling the tableview down. So, we have the refresh control, but it is hidden behind the navbar. The pull to refresh control starts from the content inset for the tableview and we already set it to 0 to have our cover image nicely fit behind the navbar. Time for another quick hack to get this to work. We need to offset the content in the header view by 64 pixels (the length of the top layout guide) and reset the top content inset for tableview to 64 pixels so that the cover image starts from behind the navigation bar and the pull to refresh from below.

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0); // This is the default and might not be necessary
        self.headerContainerViewConstraint.constant = -self.topLayoutGuide.length;
        self.tableView.tableHeaderView.frame = CGRectMake(self.tableView.tableHeaderView.frame.origin.x, self.tableView.tableHeaderView.frame.origin.y, self.tableView.tableHeaderView.frame.size.width, self.tableView.tableHeaderView.frame.size.height - self.topLayoutGuide.length);
}
Published 11 Mar 2014

I build mobile and web applications. Full Stack, Rails, React, Typescript, Kotlin, Swift
Pulkit Goyal on Twitter