UITableView auto header and footer sizes with AutoLayout
- Transfer
In this article, I will try to uncover some of the quirks of the UITableView class and show you the easiest and easiest ways to implement variable-height headers and footers. For me, simplicity is when it comes to writing user interface code, but really is not to encode any UI. In this article I will make the most of the interface builder :)
I will talk about the headers, but the same thing applies to the footers.
TableView setup
Headers in a table or simple TableView style are no different from any other UITableView row. The setup is actually quite simple.
- must be installed
sectionHeaderHeight
andestimatedHeaderHeight
. UITableView.automaticDimension
- This is what AutoLayout allows to calculate the height of each cell at runtime.estimatedHeaderHeight
must be set for a rough estimate of the overall height of its contents to display a scroll indicator.
These properties can be set in the Size Inspector when you select TableView in your storyboard.
Creating a Header View
tableView(_: viewForHeaderInSection: )
should return an instance of UIView, but guess what? UITableViewCell is a subclass of UIView. This means that we can use our storyboard to create a prototype cell that can be removed and returned from this function. In my opinion, this is the best way to declare all your views in one place, instead of many xib files scattered around your project. I created a cell prototype that consists of an ImageView on the left, a caption and a description label. In this project, a static height is not set. We want the layout to automatically calculate the height of the cell based on the size of the label content, which will be determined at runtime.
Labels are placed in the StackView and are limited to all four sides of the cell content view. I prefer to use StackView when creating views to reduce the number of restrictions.
To return the view, we call
dequeueReusableCell(withIdentifier identifier: String) -> UITableViewCell?
. We do not use a variation of the function forIndexPath:
because we do not have indexPath defined for header lines. It also forIndexPath:
claims that a reuse identifier is defined for a cell that has been excluded from the queue to prevent nil from returning. In our case, the section may be displayed without a title.guard let headerCell = tableView.dequeueReusableCell(withIdentifier: "header") else {
return nil
}
Blank Section Headers
As planned, if the header for the section in the table view in the style of the group is not defined, the framework will display an empty view with a size of 30 pixels. Apple decided that it would be strange if different sections looked like one. But sometimes we just want to break the rules. :)
To get around this, you can use a constant
CGFLOAT_MIN
. It represents the minimum non-negative value for CGFloat. The value is 1.17549435e-38F or 2.2250738585072014e-308 for 32-bit and 64-bit code, respectively. In the end, it's not zero pixels. On the other hand, in a simple table view, the height of the header can be set to any value greater than or equal to 0. For this special case, we need to use
tableView(_:estimatedHeightForHeaderInSection:)
andtableView(_:heightForHeaderInSection:)
. As indicated in the documentation, two functions must be implemented to determine the height of the custom view.Conclusion
I was puzzled to see so many hacks on StackOverflow from people wanting to implement headers of different heights. This is a simple trick that I constantly use when working with TableView, and I hope that it will be as useful to you as it is to me. Good coding! :)