0

I'm creating a custom tableHeaderView using constraints and autolayout. The problem is that my tableHeaderView appears on top of the cells.

Here's my viewDidLoad:

let tableView = UITableView()
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

//Adding subviews and setting constraints
let headerContainer = UIView()
let myView = UIView()
headerContainer.addSubview(myView)
//Setup constraints...

let myLabel = UILabel()
headerContainer.addSubview(myLabel)
//Adding many more views...

tableView.setAndLayoutTableHeaderView(header: headerContainer)

Reading this post, I've copied the suggested extension to UITableView: Is it possible to use AutoLayout with UITableView's tableHeaderView?.

extension UITableView {
    //set the tableHeaderView so that the required height can be determined, update the header's frame and set it again
    func setAndLayoutTableHeaderView(header: UIView) {
        self.tableHeaderView = header
        header.setNeedsLayout()
        header.layoutIfNeeded()
        print(header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height) //Always 0???
        header.frame.size = header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        self.tableHeaderView = header
    }
}

The problem is that the header view appears on top of the cells. On printing the size of the headerContainer after layoutIfNeeded and setNeedsLayout, the height is 0...

izaguirrejoe
  • 117
  • 8
  • 2
    "creating a custom tableHeaderView using constraints and autolayout" Don't. The position of the table header view is up to the table view, not you. You're thwarting the framework. And autosizing of the table header view has never been implemented (I have a long-standing bug about that). – matt Jun 02 '21 at 00:10
  • Hey matt, so how do I calculate the appropriate height of the tableHeaderView, after all of the views and text have been added? Keep in mind that I have multline UILabels, so the height is dynamic. – izaguirrejoe Jun 02 '21 at 00:13
  • 1
    You can use internal constraints and call `systemLayoutSizeFitting` and set the height of the header view to that, but then you have to set the header view again so that the table view hears about the change and changes the height. You would have to do that any time the label text changes. That's going to be a very unpleasant interface; the table header view is really not set up for that sort of thing. I suggest you change the whole interface architecture. – matt Jun 02 '21 at 00:15
  • I called systemLayoutSizeFitting in the extension above. Strangely, the suggested height was always 0. I tried implementing my own strategy using a scrollview, by the thought of managing the scrolling from both the scrollview and the tableview inside the scrollview sounded like a nightmare. – izaguirrejoe Jun 02 '21 at 00:19
  • I don't see you taking the table width into account. Perhaps I'm missing something... – matt Jun 02 '21 at 04:22

1 Answers1

0

When you are maintaining the frame yourself, it could be simplified to just this.

extension UITableView {

    func setAndLayoutTableHeaderView(header: UIView) {
        header.frame.size = header.systemLayoutSizeFitting(size: CGSize(width: self.frame.size.with, height: .greatestFiniteMagnitude))
        self.tableHeaderView = header
    }

}
Tarun Tyagi
  • 9,364
  • 2
  • 17
  • 30