UITableView Section Header Automatic Height Not Updated Properly

outerstorm picture outerstorm · May 16, 2017 · Viewed 8.4k times · Source

I am running into an issue with automatic/dynamic UITableView section header views that contain a UILabel that wraps (numberOfLines = 0). The height is not being calculated properly, especially once you scroll the table and the views are reused. Sometimes the UILabel wraps, sometimes it is truncated, sometimes one or more of the labels are not visible, and sometimes there is extra spacing between the labels. The custom view contains a vertical UIStackView with three UILabels, once of which wraps.

A complete sample app demonstrating the issue can be found at https://github.com/outerstorm/tableviewHeaderTest.

The section header heights are set to automatic in viewDidLoad with the following:

    tableView.sectionHeaderHeight = UITableViewAutomaticDimension
    tableView.estimatedSectionHeaderHeight = 30.0

and also have implemented the following heightForHeaderInSection just to try to get it to work:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return UITableViewAutomaticDimension
}

I have also tried calling setNeedsLayout() and layoutIfNeeded() at various points to no avail. Any suggestions would be greatly appreciated.

Below is a screenshot of the behavior seen in the app. The first section is cutoff and the second section is too tall:

enter image description here

Answer

PGDev picture PGDev · May 29, 2017

I have faced this kind of issue recently.

I solved it by setting preferredMaxLayoutWidth of multiline labels, i.e.

Before setting the value in labels, set their preferredMaxLayoutWidth as:

self.label1.preferredMaxLayoutWidth = self.label1.frame.size.width
self.label2.preferredMaxLayoutWidth = self.label2.frame.size.width
self.label3.preferredMaxLayoutWidth = self.label3.frame.size.width