If, like me, you’ve found yourself needing to implement a collapsing header in your iOS app, look no further. This blog post will walk you through a simple implementation of a collapsing header in an iOS app using UIKit.
The main components are:
Start by constructing the Containing View Controller and adding the Header.
Next, we add a Container View to our Containing View Controller, this will hold our UIScrollView.
Now that we’ve got our UI constructed, we add the code. Our ContainingViewController should look like this (note, we’ve added the IBOutlets ahead of time).
For the purposes of this example, our UIScrollView implementation is a UITableView. Note that this can be swapped out for any UIScrollView implementation.
The majority of the code in the TableViewController is boilerplate, so I’ve excluded it from this post. The important points are above. It conforms to ScrollViewContained protocol. This protocol simply defines that it will have a scrollDelegate property. The other important point is that on scrollViewDidScroll, we call the delegate’s scrollViewDidScroll method.
The two protocols are defined as follows:
Now going back to our ContainingViewController, we add a helper variable:
and we override viewDidLoad:
Two important things to note in the viewDidLoad method:
But wait! Our controller doesn’t implement the ScrollViewContainingDelegate protocol! Let’s add that code now:
This delegate implementation is the important part of the code so I’ll go over it in depth. The way that this implementation works, is that as you scroll your UIScrollView, the header is scrolled up offscreen, creating the collapsing effect. In this case, we just change the header color when we’re at the top (i.e. fully collapsed state), however, for more complex UI you could animate alongside this scrolling by calculating the scroll percentage as a percentage of the maxScrollAmount variable.
We calculate the value of the newTopConstraintConstant, it is negative because we are adjusting the constraint to move the header offscreen.
We then set the constant, by taking the maximum between -maxScrollAmount and newTopConstraintConstant, and then the minimum between that value and 0. What does this accomplish? By doing this, we’re ensuring both that the header doesn’t get scrolled farther offscreen than its total height. Second, by not allowing it to be greater than zero, we’re saying that once the header is fully expanded it cannot scroll down further.
Lastly, we handle the state change of being at the top in the full collapsed state, and in this case we just change the background color.
And that’s it, you now have a functional collapsing header. If you want to take this further, it is possible to animate alongside the collapsing of the header, so that it changes as it scrolls. If you want to check out the source code for this example, it can be found here.