UITableView 動態(tài)高度計算

  • 一. 設(shè)置 estimatedRowHeight

一般來講計算cell的高度需根據(jù)數(shù)據(jù)模型的內(nèi)容長度,決定單元格高度,按照常規(guī)的方式,需要先給出單元格高度,代理才會執(zhí)行cellForRow函數(shù),如果height為0的話,cellForRow函數(shù)就不執(zhí)行了,而我們的計算卻發(fā)生在cellForRow函數(shù)中,計算完成后再刷新,但是這樣不可行。

正確方式: 首先設(shè)置tableView的預(yù)估高度,這樣的話,代理就會首先執(zhí)行cellForRow函數(shù),這樣就可以先計算,計算完成后保存起來,然后再執(zhí)行heightForRow函數(shù),讀取剛才保存的值。

    tableView.estimatedRowHeight = 500
  • 二. 設(shè)置 beginUpdates 以及 endUpdates 函數(shù)

對于cell中有按鈕或者其他出發(fā)事件時動態(tài)修改cell高度的情況,可以在觸發(fā)事件中調(diào)用 beginUpdatesendUpdates 兩個函數(shù),該函數(shù)的作用區(qū)別于調(diào)用 reloadData,刷新時只會更新高度,而不會重新調(diào)用 cellForRow 函數(shù)。

    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
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容