UITableView的tableHeaderView高度的自适应
UITableView的tableHeaderView高度的自适应
前段时间碰到一个要求对UITableHeaderView的高度随内容高度自适应的需求。讲到根据内容自适应,在Autolayout到来后越来越容易了。
Apple对自适应的支持
之所以UIlabel,UIButton, UIImageView能根据内容自适应,是因为有一个IntrinsicContentSize。有了它就可以自己根据内容调整大小,再也不用量宽和高了。对IntrinsicContentSize的支持Apple也给了一个表:
| View | Intrinsic Content Size |
|---|---|
| View And NSView | No intrinsic content size. |
| Sliders | Defines Only The Width. |
| Labels,buttons,switches,and text fields | Define both the height and the width. |
| Text views and Image views | intrinsic content size can vary. |
* UIView和NSView是没有IntrinsicContentSize的。
* Sliders只有with有这个属性。 Sliders只能定义width。Sliders的height拥有IntrinsicContentSize(感谢@凸小布,发现了这个问题)
* Labels, buttons, switches, text fields比较棒,属性完美支持
* Text views和image views也挺好,在有内容的时候支持,没有内容的时候不支持。
虽然UIView没有IntrinsicContentSize,但如果我们自定义一个View,又想要他拥有默认宽高,只需要重写IntrinsicContentSize方法,便可让其拥有默认的宽高。在storyboard/xib中的Size Inspector也有争对这一块的设置。(比如UIImage放在UIScrollView中,当没有给UIImage设置图片时,storyboard会有约束警告,在Size Inspector中设置placeHolder的宽高即可)。
tableHeaderView高度自适应
这里自定义的tableHeader的结构如下图
因为iOS并没有提供像给UITableViewCell设置自适应高度的方法
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
所以tableHeaderView的高度还是要根据内容来计算,只是这个计算过程可以充分利用其子视图的intrinsic特点来自动给我们算出来,这里通过给UITableView扩展一个方法来做,如下
extension UITableView {
func setAndLayoutTableHeaderView(header: UIView) {
self.tableHeaderView = header
//Tip:这里要先计算子视图的高度后,再去更新tableHeaderView的布局
for view in header.subviews {
guard let label = view as? UILabel where label.numberOfLines == 0 else { continue }
//设置子视图的preferredMaxLayoutWidth
label.preferredMaxLayoutWidth = CGRectGetWidth(label.frame)
}
//更新tableHeaderView的布局
header.setNeedsLayout()
header.layoutIfNeeded()
var frame = header.frame
// let height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
// //let height = header.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize).height
// frame.size.height = height
let size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
frame.size = size
header.frame = frame
self.tableHeaderView = header
}
}
最后调用再这样简单调用一下:
override func viewDidLoad() {
super.viewDidLoad()
//tableHeaderView指定为storyboard中自定义的headerView
self.tableView.tableHeaderView = headerView
//设置tableHeaderView高度自
self.tableView.setAndLayoutTableHeaderView(headerView)
self.tableView.tableFooterView = footerView
//self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
//self.tableView.estimatedSectionHeaderHeight = 1;
}