Sticky "header" in UITableView.

The same header as in AppStore main page.

In this story, I want to share my experience of creating a header view with pages in it, the same as AppStore app has on the main page. It looks like this:

Original AppStore app. Main page.

As you can see, header always stuck/pinned to the top of UITableView. And it’s not a simple UITableView header as I thought at the very start ☹️. So let’s dive into XCode and try to create it together! 🤜

XCode project.

Storyboarding.

In XCode simply create a new single view application, name it whatever you want, in my case, it’s Medium-UITableViewHeader, and open a Main.storyboard file. Here you already have a blank UIViewController, it’s fine, let’s add a UIScrollView in it and stretch to fill all controller view. Why scroll view, well, this is the key to creating this kind of sticky/pinned table view header. It allows a user to scroll up and down dragging both header and table view and user have an ability to scroll header left and right.

So our next step is to add a blank UIView to handle stuff inside. Through this view, we will change our scroll view size (height). Add a UIView and stretch it as well to fill scroll view.

Now we need to add some constraints. The view will have a zero spacing constraint to all parent scroll view sides.

And we need to set view horizontally in container property.

We will still have everything reddish, that’s because we haven’t setup scroll view constraints. Add scroll view 4 constraints for all sides, like we did for the view above. At this point we have something like this:

So our next step is to add a UITableView inside the view and set constraints to fill it. Result:

Perfect!
Now we need to add a header, but not a simple one, it should handle several pages inside…🤔 For handling paging Apple give as a UIPageViewController but hold on, we can’t drag a controller inside a controller… Actually, we can, using a ContainerView 😌. Search for it in Object Library and drag it in your controller. BUT! you need to drag it in the project view’s hierarchy, otherwise, his container becomes a table view cell.

As you can see this little controller is UIViewController and we need to replace it with UIPageViewController. Simply delete UIViewController drag into our storyboard new UIPageViewController and make a segue from container view to page controller called Embade.

Almost there! Now, let’s add constraints for this container. Pin it to the top, left, right and with 150 height. Apply some random background color for container view just to see it while app running.

Run the app. You will see the container view at the top and blank table view cells. But while scrolling, table view header is not moving at all. For now, we don’t scroll out “container” UIScrollView, and to do that we need to disable scrolling in the tableView.

Select our tableView and in the attributes inspector find and uncheck Scrolling Enabled property. In addition to seeing that everything ok, select “container” UIScrollView and in attributes inspector check Bounce Vertically property. At this stage we have something like this:

The next step is to connect our view’s with code. Open default ViewController.swift file and create needed outlets.

And to get control of the position of our pageControllerContainerView we need an outlet for its top constraint.

Not the best naming, I know 😅. But you can name it better.

Now lets setup delegates (TableView delegate and data source, ScrollView delegate). You could do it through storyboard or code. I just do it in code.

After that, we need to inherit UITableViewDelegate and UITableViewDataSource. And basic functions.

Add a top edge inset for table view to adjust our header height.

Result:

Now let’s work with header top anchor. Add a variable for keeping height of our pageControllerContainerView calls pageContainerInitialHeight. Set this variable height in the viewDidLoad method. And do some anchor changing in scrollViewDidScroll(_:) method.

Result:

Cool! Now we need to adjust scroll view content height to handle whole table view content + header. Unfortunately, I couldn’t do this through the scrollView.contentSize property, it’s just do nothing. So for this purpose, I’ve created rootContainerView. To change height we actually need an anchor for it, add it and connect with code.

And the last thing to make everything work. Call tableView.layoutIfNeeded() to recalculate table content height and set this content size height to our previously created height constraint.

Completed controller code and hierarchy in the screenshot below.

Completed code in GistBox snippet

Done!☺️

What have we done:

Conclusions

There is a lot of different stuff but in general, it’s easy to do. Once you do it yourself, everything would be clear. I think to make a second part for this tutorial where I would implement page controller itself, so subscribe, more stuff cumming!🤗

Thanks for reading. Thats my first story, so do not judge strictly.

Stay legendary!🤘

)
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade