iOS踩过的坑之tableView动态高度计算

UITableView 动态高度计算

  • 一. 设置 estimatedRowHeight

一般来讲计算cell的高度需根据数据模型的内容长度,决定单元格高度,按照常规的方式,需要先给出单元格高度,代理才会执行cellForRow函数,如果height为0的话,cellForRow函数就不执行了,而我们的计算却发生在cellForRow函数中,计算完成后再刷新,但是这样不可行。

正确方式: 首先设置tableView的预估高度,这样的话,代理就会首先执行cellForRow函数,这样就可以先计算,计算完成后保存起来,然后再执行heightForRow函数,读取刚才保存的值。

    tableView.estimatedRowHeight = 500
  • 二. 设置 beginUpdates 以及 endUpdates 函数

对于cell中有按钮或者其他出发事件时动态修改cell高度的情况,可以在触发事件中调用 beginUpdatesendUpdates 两个函数,该函数的作用区别于调用 reloadData,刷新时只会更新高度,而不会重新调用 cellForRow 函数。

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.beginUpdates()
        let key = String(format: "ip:(%u,%u)", indexPath.section, indexPath.row)
        allHeight[key] = 200
        tableView.endUpdates()
    }

example

  • vc
import UIKit

class TestVC: UIViewController {
    
    public var allHeight = [String: CGFloat]()
    
    lazy var tableView: UITableView = {
        let temp = UITableView()
        temp.delegate = self
        temp.dataSource = self
        temp .register(TestTableViewCell.self, forCellReuseIdentifier: TestTableViewCell.description())
        return temp
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.frame = view.bounds
        view.addSubview(tableView)
        
        tableView.estimatedRowHeight = 500;
        tableView.reloadData()
    }
}

extension TestVC: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        debugPrint("cellForRowAt")
        
        guard let cell = tableView.dequeueReusableCell(withIdentifier: TestTableViewCell.description(), for: indexPath) as? TestTableViewCell else { return UITableViewCell() }
        
        cell.content = "获取 = \(indexPath.row)"
        let key = String(format: "ip:(%u,%u)", indexPath.section, indexPath.row)
        if !allHeight.keys.contains(key) {
            let value = cell.dynamicHeight
            allHeight[key] = value
        }
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        
        debugPrint("heightForRowAt")
        
        let key = String(format: "ip:(%u,%u)", indexPath.section, indexPath.row)
        guard let height = allHeight[key] else { return 0 }
        return height
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.beginUpdates()
        let key = String(format: "ip:(%u,%u)", indexPath.section, indexPath.row)
        allHeight[key] = 200
        tableView.endUpdates()
    }
}
  • cell
import UIKit

class TestTableViewCell: UITableViewCell {
    
    public var content: String? {
        didSet {
            dynamicHeight = 100
            self.textLabel?.text = content
        }
    }
    
    private (set) public var dynamicHeight: CGFloat = 0
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
}

你可能感兴趣的:(iOS踩过的坑之tableView动态高度计算)