Section Header View
昨天做项目,需要一个select all功能,为了不随table滚动而消失,所以我打算把它弄到section header view中,永远悬停在上面。
二话不说,上代码:
- 配置Header View
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
//配置view
//...
let selectAllButton = UIButton()
//配置button
//...
headerView.addSubview(selectAllButton)
//为button添加autolayout约束
//记住,添加完约束后,一定加上下面这句话。因为约束添加后,在view显示出来之前,它依旧不会根据约束调整自己的frame。它调整frame是在显示出来的时候。因此这个时候你如果获取它的frame,依旧是未添加约束前的frame。调用这个方法,是告诉view,现在、马上、立刻根据我的约束去布局你自己。这之后,就可以放心获取它的正确frame了
selectAllButton.layoutIfNeeded()
//获取button的高度,根据它的高度设置section header高度
sectionHeaderViewHeight = CGRectGetMaxY(selectAllButton.frame) + 10
return headerView
}
- 设置高度
var sectionHeaderViewHeight:CGFloat = 0
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return sectionHeaderViewHeight
}
问题1:
感觉很对的样子,信心满满地运行。最后的结果是。。。根本没有什么卵header view,连影子都没有。
鬼影子都没有一个
- Why?
在调用viewForHeaderInSection之前,系统就会调用heightForHeaderInSection,如果高度事先就返回 0,那么系统永远不会调用viewForHeaderInSection。因为高度是0,它就算获取到了view,观众们也看不到,何必做无用功?
因此,如果希望显示header view,我们的高度永远永远不要返回0。改正如下:
var sectionHeaderViewHeight:CGFloat = 30.0
问题2:
好,这次应该没问题了,让我们荡起双桨,再次运行。等待30秒后。。。什么鬼!?高度不够啊!只有30!我不是根据button重新设置过高度吗!
什么鬼?高度不够!
- Why?
刚才我们已经知道,heightForHeaderInSection调用在viewForHeaderInSection。意思是我们在viewForHeaderInSection中根据button高度设置的height,虽然保存到sectionHeaderViewHeight这个变量,但是系统没有再调用heightForHeaderInSection,因此现在的高度依旧是30。那么解决的思路是,我们需要系统在调用viewForHeaderInSection后,再次调用heightForHeaderInSection,重设高度。
经过我的测试,我发现,系统会在viewWillAppear后,调用viewForHeaderInSection。我们需要在viewForHeaderInSection被调用后,让系统重新调用一次heightForHeaderInSection。因此,在viewDidAppear中让它重新调用一次,最合适不过了。
千万不要在viewDidAppear中手动调用heightForHeaderInSection哦,一定是没有效果的!
正确的做法是:
override func viewDidAppear(animated: Bool) {
self.tableView.reloadData()
}
- 最后:还有其他的解决方案,更加复杂一些。我在stackoverflow上有回答另一种方案。
请参见:
http://stackoverflow.com/questions/9564323/dynamic-heightforheaderinsection/36617536#36617536
问题下也有另外两个回答。