根据View的内容动态设置section header高度

根据View的内容动态设置section header高度_第1张图片
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重新设置过高度吗!

根据View的内容动态设置section header高度_第2张图片
什么鬼?高度不够!
  • 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
    问题下也有另外两个回答。

你可能感兴趣的:(根据View的内容动态设置section header高度)