让UITableView的tableHeaderView支持autoLayout

默认情况下,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")
    }
    
}

Demo地址

你可能感兴趣的:(让UITableView的tableHeaderView支持autoLayout)