在 tableHeaderView 中使用 AutoLayout

我一直在寻找如何在 tableHeaderView 使用AutoLayout。设置 tableViewtableHeaderView 感觉就像在黑洞中投掷视图一样。我们不知道它与层次结构中的其他视图有何关联。

最后,我找到了一个适合我的解决方案,没有显式的 frame 计算。

我使用 UIViewControllerUITableView 作为子视图,而不是UITableViewController

要点:

  1. 设置 table header view
  2. header viewcenterXwidthtop 锚点固定到 table view.
  3. tableHeaderView 调用 layoutIfNeeded 更新他的大小。
  4. 重新赋值 tableHeaderView

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ...In viewDidLoad()
// 1.
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
// headerView is your actual content.
containerView.addSubview(headerView)

// 2.
self.tableView.tableHeaderView = containerView
// 3.
containerView.centerXAnchor.constraint(equalTo: self.tableView.centerXAnchor).isActive = true
containerView.widthAnchor.constraint(equalTo: self.tableView.widthAnchor).isActive = true
containerView.topAnchor.constraint(equalTo: self.tableView.topAnchor).isActive = true
// 4.
self.tableView.tableHeaderView?.layoutIfNeeded()
self.tableView.tableHeaderView = self.tableView.tableHeaderView

To update the header frame on device rotation

处理设备旋转需要重新布局的情况:

1
2
3
4
5
6
7
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
DispatchQueue.main.async {
self.tableView.tableHeaderView?.layoutIfNeeded()
self.tableView.tableHeaderView = self.tableView.tableHeaderView
}
}

完整Demo: TableHeaderViewWithAutoLayout

Extension

1
2
3
4
5
6
7
8
9
10
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()
header.frame.size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
self.tableHeaderView = header
}
}

使用:

1
2
3
4
let header = SCAMessageView()
header.titleLabel.text = "Warning"
header.subtitleLabel.text = "Warning message here."
tableView.setAndLayoutTableHeaderView(header)

参考资料