bobcobb
bobcobb

Reputation: 149

UITableView header is overlapping the content of its cells

I am working on a UITableViewController view that has a bunch of content in the UITableView header of varying height. The height requirement of the entire header will vary, so I need to set it dynamically based on which content is displayed in there.

Below is what I have been trying after searching for potential solutions. The UITableView.automaticDimension doesn't seem to be doing anything. Setting tableView.sectionHeaderHeight to a static number works, but I can't quite get it to be set dynamically.

This is all being done programmatically.

Am I going about this the correct way? Basically after all the subviews have been added to the headerView I want to set the height of the entire header.

ViewDidLoad:

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self as! UITableViewDataSource
        tableView.sectionHeaderHeight = UITableView.automaticDimension
        tableView.estimatedSectionHeaderHeight = 200;
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }

Supposed to be setting the header height?

    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return UITableView.automaticDimension
    }
    override func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
        return 200
    }

Adding the header content:

    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let v = headerView
        v.translatesAutoresizingMaskIntoConstraints = false
        v.addSubview(headingLabel)
        v.addSubview(subheadingLabel)
        v.addSubview(additionalContent)
        headerConstraints()
        return v
    }

This is what I see: This is what I see

This is what I'm kind of hoping to see: This is what I'm hoping to see

Any suggestions?

Thanks!

Upvotes: 1

Views: 4831

Answers (3)

nayem
nayem

Reputation: 7585

The problem is:

v.translatesAutoresizingMaskIntoConstraints = false

When you provide your custom view as a header/footer for the table view section, you don't need to modify the auto resizing mask on the returned view itself. To my best understanding, doing this breaks table view's internal setup.

But if you register a UITableViewHeaderFooterView subclass as the header/footer, you have to consider that option as you are taking control of configuring the entire header/footer.


Now, I suppose your

let v = headerView
. . .
headerConstraints()

codes are correct. If that is so, the above change should work as expected.


Otherwise below is an example you can try:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let v = UIView()

    let headingLabel = UILabel(frame: .zero)
    headingLabel.translatesAutoresizingMaskIntoConstraints = false
    headingLabel.text = "View Header"
    headingLabel.font = UIFont.systemFont(ofSize: 30, weight: .heavy)
    headingLabel.textColor = .black

    let subheadingLabel = UILabel(frame: .zero)
    subheadingLabel.translatesAutoresizingMaskIntoConstraints = false
    subheadingLabel.text = "Subheader Content"
    subheadingLabel.font = UIFont.systemFont(ofSize: 15, weight: .semibold)
    subheadingLabel.textColor = .gray

    let additionalLabel = UILabel(frame: .zero)
    additionalLabel.translatesAutoresizingMaskIntoConstraints = false
    additionalLabel.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    additionalLabel.numberOfLines = 0
    additionalLabel.font = UIFont.systemFont(ofSize: 15, weight: .regular)
    additionalLabel.textColor = .white
    let additionalContent = UIView(frame: .zero)
    additionalContent.translatesAutoresizingMaskIntoConstraints = false
    additionalContent.backgroundColor = .black
    additionalContent.addSubview(additionalLabel)
    additionalLabel.leadingAnchor.constraint(equalTo: additionalContent.leadingAnchor, constant: 10).isActive = true
    additionalLabel.trailingAnchor.constraint(equalTo: additionalContent.trailingAnchor, constant: -10).isActive = true
    additionalLabel.topAnchor.constraint(equalTo: additionalContent.topAnchor, constant: 10).isActive = true
    additionalContent.bottomAnchor.constraint(equalTo: additionalLabel.bottomAnchor, constant: 10).isActive = true

    let stackView = UIStackView(frame: .zero)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.axis = .vertical
    stackView.alignment = .fill
    stackView.distribution = .fill
    stackView.spacing = 8
    stackView.addArrangedSubview(headingLabel)
    stackView.addArrangedSubview(subheadingLabel)
    stackView.addArrangedSubview(additionalContent)
    v.addSubview(stackView)
    stackView.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 16).isActive = true
    stackView.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -16).isActive = true
    stackView.topAnchor.constraint(equalTo: v.topAnchor, constant: 16).isActive = true
    stackView.bottomAnchor.constraint(equalTo: v.bottomAnchor, constant: -16).isActive = true

    return v
}

And don't forget (if you need automatic height calculation):

override func viewDidLoad() {
    super.viewDidLoad()
    . . .
    tableView.sectionHeaderHeight = UITableView.automaticDimension
    tableView.estimatedSectionHeaderHeight = 100
    . . .
}

Upvotes: 3

user2931321
user2931321

Reputation: 476

Use UITableView style as grouped.

Upvotes: 2

Xuan-Gieng Nguyen
Xuan-Gieng Nguyen

Reputation: 846

I believe this can be resolved if you set the clipsToBounds of tableView to be true.

Using code:

tableView.clipsToBounds = true

Using interface builder:

enter image description here

Upvotes: 1

Related Questions