Stretchy table header view (iOS)
Give your UITableView header view an extra touch by making it stretch as the table view bounces past the edge of its content.
UITableViews is probably one of the most used UIView subclasses in iOS apps. And where there is a UITableView, you will often find it accompanied by a tableHeaderView to display above its content.
To give the table header view a nice touch, a lot of apps pin it to the top of the screen, and make it stretch as the UITableView bounces past the edge of its content. In this article we’ll take a look at how easy it actually is to make your very own stretchy table header view.
Key takeaways
- Create a base table header view class, and have it expose a contentView that subclasses will add their content to (much like UICollectionViewCell does it).
- Have this base class expose a method to be called when UITableView.scrollViewDidScroll(_:) happens.
- Let this method update the constraints on the base table header view’s contentView, so that it expands when the UITableView scrolls (based on the UITableView.contentOffset).
- Create your custom subclass of the base table header view class, add its content to contentView, and apply it to UITableView.tableHeaderView.
For those of you who want to look at some example code right away, the complete example can be found here: https://github.com/thomsmed/ios-examples/tree/main/StretchyTableViewHeader
The example app
As an example we’ll make a simple app for browsing octocats. Octocat is the mascot of GitHub, and over at https://octodex.github.com/ there is a nice collection of different octocats we can borrow 😉
The app will look something like in the gif below — a simple app for browsing octocat images, and with a UITableView header view that stretches as the table view bounces past the edge of its content.
To give us some nice syntax sugar while we write Auto Layout Constraints in our app, we’ll use the awesome TinyConstraints library.
Stealing the base for the app
As a base for the app, we’ll use the code described in my other post: Transition images to full screen animated (iOS).
We will modify it and add code for our stretchy table fheader view.
StretchyTableHeaderView
First we’ll create a base class for our stretchy header view — StretchyTableHeaderView.
After checking out the docs about UITableView.tableHeaderView, we understand that the table header view’s width is fully managed by the UITableView, and that its height need to be well defined in its frame property. And since the table header view will be part of the UITableView’s scrolable content, we do not want to update the actual header view’s frame as the UITableView bounces. That would just cause the content of the UITableView to be shifted down. We want the header view to stick at the top of the UITableView — and possibly extend beyond any safe area — as well as stretch when the UITableView bounces past the edge of its content.
A solution to this is to add a subview that will act as a wrapper for the other views inside our StretchyTableHeaderView — a contentView. We will constrain this contentView to the size of the parent, but with the possibility to grow beyond in height — beyond the top of parent view itself. And by utilising the fact that UITableView is a subclass of UIScrollView, we will make StretchyTableHeaderView expose a method to be called as the UITableView scrolls. This method will update the top constraint of StretchyTableHeaderView’s contentView to match the distance scrolled by the UITableView plus any safe area at the top.
OctocatTableHeaderView
Lets now extend the StretchyTableHeaderView to make the actual header we will use as the view for UITableView.tableHeaderView — the OctocatTableHeaderView.
We’ll add an UIImageView that will fill the StretchyTableHeaderView’s contentView, and therefor appear to stretch as the UITableView bounces past the edges of it content.
In addition we’ll add UILabel wrapped inside a UIVisualEffectView, and pin it to the lower left corner of the contentView’s safe area layout.
Updating the base of the app
With our base table header view, StretchyTableHeaderView and our OctocatTableHeaderView. All that is left is to actually apply the header view to the UITableView. A couple of simple modifications to the already existing TableViewController class, and we’re all set.
We attach our OctocatTableHeaderView to the UITableView in UIViewController.viewDidLoad(), and override UIScrollViewDelegate’s scrollViewDidScroll(_:) method so that the StretchyTableHeaderView’s contentView gets updated as UITableView scrolls.
Summary
In this article we’ve made our very own stretchy table header view, to give that extra touch to our UITableView header view. We used the result of another article, Transition images to full screen animated (iOS), as our base app, and extended upon it to add a stretchy table header view.
As mentioned at the start of this article, the complete source code can be found here: https://github.com/thomsmed/ios-examples/tree/main/StretchyTableViewHeader
Happy coding!