首先,标题党一枚,UITableViewHeader 是没有办法动态调整

ios uiview 获取 高度 uitableview headerview高度更新_tableViewHeader

But,我们可以通过重新赋值 Header 来达到动态调整的效果

示例

需求:header包含一个动态文本标签,具体内容多少可能会随业务多久修改,这里就涉及一个问题,需要多行显示,Header要随之动态变化高度。

需求界面

单行显示

ios uiview 获取 高度 uitableview headerview高度更新_UITableView_02


多行显示

ios uiview 获取 高度 uitableview headerview高度更新_tableViewHeader_03

自定义HeaderView

使用Autolayout布局自定义HeaderView,一定要保证控件之间满足布局约束。

关键代码:

let label = UILabel()
 label.numberOfLines = 0 // 多行
 label.preferredMaxLayoutWidth = Screen.width-8*2-15*2 // 【重点】文本最大约束宽度
 // 添加到 header 中和添加约束

这里最重要的是设置 UILabel 的 preferredMaxLayoutWidth, 使其在没有添加约束的时候具备计算size的能力。

UILabel 的 preferredMaxLayoutWidth

当多行 Label 时,首选最大宽度。用于在 Autolayout 布局中,进行换行依据, 如果不为0,则用来计算 intrinsicContentSize


关于 preferredMaxLayoutWidth 的结论:

  1. 行数为1的 UILabel,preferredMaxLayoutWidth 不会影响。
  2. 多行时
  1. UILabel 具备完整约束,使用 preferredMaxLayoutWidth 作为宽度换行,为0时则不会换行。
  2. UILabel 不具备完整约束,以自身约束作为宽度换行,为0不影响。
    但是这这两种情况都会在调用其父视图(或者父视图的父视图)的 [superView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] 方法计算其父视图最小宽高时,使用 preferredMaxLayoutWidth 作为换行宽度


初始化添加HeaderView

private func setupTableView(){
    let header = SearchMyRaceHeaderView(frame: CGRect(x: 0, y: 0, width: Screen.width, height: 0))
    tableView.tableHeaderView = header
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dWoS0aUb-1596767693677)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

更新约束

private func sizeHeaderTofit(){
    let headerView = tableView.tableHeaderView! // 获取headerView
    headerView.setNeedsLayout()
    headerView.layoutIfNeeded()  // 使布局立即生效
    
    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
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d28amdmH-1596767693678)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    sizeHeaderTofit()
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ngd1kqz3-1596767693679)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

Tips:

  1. 如果需要修改tableHeaderView高度,必须重新赋值,单纯修改frame布局没有效果的。
  2. 基于约束布局的控件可以通过, 立即生效约束和systemlayoutSizeFitting()方法获取size。从而与frame布局进行桥接转化

扩展:通过 Xib加载的 Header 高度异常

对于复杂的 Header 我们更喜欢使用 xib 来布局,但是通过 xib 初始化加在 Header 的 View总会出现高度和预期或者预设值不一样的问题。

后来经过反复测试发现,将创建的 xib 的 View删除,然后再自己加一个 View 进去即可正确显示高度。