Search code examples
iosswiftautolayouttableviewsnapkit

Avoid sticky header view when tableview scrolls with Auto Layout


Currently when table content is scrolling, the headerLabel follows scroll and sticks to the top. How can I have avoid this behaviour with Auto Layout?

var tableView: UITableView!

let headerLabel: UILabel = {
    let label = UILabel(frame: .zero)

    label.font = UIFont.boldSystemFont(ofSize: 34.0)
    label.textColor = .black
    label.textAlignment = .center

    return label
}()

override func viewDidLoad() {
    super.viewDidLoad()

    let barHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height

    tableView = UITableView(frame: CGRect(x: 0, y: barHeight, width: view.frame.width, height: view.frame.height - barHeight))
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "tableCell")
    tableView.dataSource = self
    tableView.delegate = self
    tableView.separatorStyle = .none

    view.addSubview(headerLabel)
    view.addSubview(tableView)

    headerLabel.snp.makeConstraints { (make) in
        make.top.equalTo(view).offset(35)
        make.width.equalToSuperview()
    }

    tableView.snp.makeConstraints { (make) in
        make.top.equalTo(headerLabel.snp.bottom)
        make.left.bottom.right.equalToSuperview()
    }
}

The headerLabel should scroll with tableView and should not look like sticky header.


Solution

  • Currently your table view and your label are siblings inside your UIViewController's view, which means your label is not part of the table view so it won't scroll with it. You can add the label to a UIView, set it's constraints and then set the tableHeaderView property of the table view. Here's a sample code with some hardcoded values:

        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "some text"
        label.sizeToFit()
    
        let headerView = UIView()
        headerView.translatesAutoresizingMaskIntoConstraints = false
        headerView.addSubview(label)
    
        tableView.tableHeaderView = headerView
    
        headerView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor).isActive = true
        headerView.heightAnchor.constraint(equalToConstant: 80).isActive = true
        headerView.widthAnchor.constraint(equalTo: tableView.widthAnchor).isActive = true
    
        label.leftAnchor.constraint(equalTo: headerView.leftAnchor, constant: 50).isActive = true
    
        tableView.tableHeaderView?.layoutIfNeeded()