默認情況下,UITableView的tableHeaderView是不支持autoLayout的,需要直接設置frame,但在tableHeaderView高度可能會變化的情況下,直接設置frame比較麻煩。
手動設置tableHeaderView的frame方法
首先需要知道的是,修改tableHeaderView的frame,是不能直接生效的,需要調用一下set方法。如下所示:
var tempFrame = headerView.frame
tempFrame.size.height = smallSize.height
headerView.frame = tempFrame // 直接更改frame無效
tableView.tableHeaderView = headerView // 【重點】重新為 TableView 賦值 Header
tableHeaderView支持autoLayout的方法
代碼類似如下:
func refreshTableHeaderViewFrame() {
if let headerView = tableView.tableHeaderView {// 獲取headerView
let smallSize = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) //獲取到基于Autolayout布局控件盡可能小的大小
var tempFrame = headerView.frame
tempFrame.size.height = smallSize.height
headerView.frame = tempFrame // 直接更改frame無效
tableView.tableHeaderView = headerView // 【重點】重新為 TableView 賦值 Header
self.tableView.reloadData()
}
}
這里需要注意的是代碼里的
MAHeaderView
里面的子控件能撐開該視圖(即可以自適應高度)。
以下是MAHeaderView的源碼:
class MAHeaderView: UIView {
public var title: String = "" {
didSet {
self.titleLabel.text = title
}
}
private lazy var headerView: UIView = {
let headerView = UIView()
headerView.backgroundColor = UIColor.red
headerView.layer.cornerRadius = 45
return headerView
}()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.black
label.font = UIFont.systemFont(ofSize: 17)
label.numberOfLines = 0
return label
}()
private lazy var lineView: UIView = {
let lineView = UIView()
lineView.backgroundColor = UIColor.black
return lineView
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(self.headerView)
self.addSubview(self.titleLabel)
self.addSubview(self.lineView)
self.headerView.ma_makeConstraints { (make) in
make.topLeft.equalTo(self).offset(15)
make.size.ma_equal(90)
make.bottom.lessThanOrEqualTo(self).offset(-15)
}
self.titleLabel.ma_makeConstraints { (make) in
make.top.equalTo(self.headerView)
make.left.equalTo(self.headerView.ma_right).offset(15)
make.right.equalTo(self).offset(-15)
make.bottom.equalTo(self).offset(-15).priority(.defaultHigh)
}
self.titleLabel.setContentHuggingPriority(UILayoutPriority.init(1000), for: .vertical)
self.lineView.ma_makeConstraints { (make) in
make.bottomLeftRight.equalTo(self)
make.height.ma_equal(0.5)
}
}
override func layoutSubviews() {
super.layoutSubviews()
// 這句話比較關鍵,如果界面上有UILabel,需要設置UILabel的preferredMaxLayoutWidth,(如果不設置MAHeaderView就不能自適應高度),如果最大寬度固定,可以在處理約束的位置設置;如果受其他view影響,可以在layoutSubviews中設置。
self.titleLabel.preferredMaxLayoutWidth = self.frame.size.width - 15 - 90 - 15 - 15
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}