簡體   English   中英

如何動態調整表格視圖標題的大小?

[英]How to dynamically resize table view header?

當人們點擊加載更多時,我想動態調整表格視圖標題的大小。 發生的情況是,當人們點擊加載更多時,新內容會添加到表格視圖標題中,因此高度會發生變化。 我事先不知道新的高度。

我怎樣才能做到這一點? 我現在正在做的是當人們點擊“加載更多”時,我執行下面的代碼。

@objc func expandDesc(sender: UIButton) {
    loadMoreDesc = !loadMoreDesc
    tableView.reloadData()
}

我可以在上面的代碼中添加什么來動態調整表視圖標題的大小?

只需使用約束,您就可以為它們設置動畫。 您不必為此重新加載整個表視圖。 您可以保持對標題的弱引用並更改其狀態,如果按下更多,則為約束設置動畫,如果是文本您想要適合,請使用 StackView 並添加/刪除 UILabel 到堆棧視圖,它應該可以完美運行。

自動布局不會自動更新表頭視圖的大小,因此我們需要“手動”進行。

我們可以使用這個擴展來幫助:

extension UITableView {
    func sizeHeaderToFit() {
        guard let headerView = tableHeaderView else { return }

        let height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height

        var frame = headerView.frame
        
        // avoids infinite loop!
        if height != frame.height {
            frame.size.height = height
            headerView.frame = frame
            tableHeaderView = headerView
        }
    }
}

現在,當我們更新表頭視圖的內容時——這會導致它的高度改變——我們可以調用.sizeHeadrToFit()

這是一個完整的例子:

簡單的多行單元格- 青色標簽

class MultilineCell: UITableViewCell {
    
    let label: UILabel = {
        let v = UILabel()
        v.numberOfLines = 0
        return v
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        label.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(label)
        let g = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            // constrain label to the cell's margins guide
            label.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            label.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            label.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            label.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
        ])
        label.backgroundColor = .cyan
    }
    
}

表標題的多行視圖- 紅色視圖中的黃色標簽

class MyTableHeaderView: UIView {
    
    let label: UILabel = {
        let v = UILabel()
        v.numberOfLines = 0
        return v
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        label.translatesAutoresizingMaskIntoConstraints = false
        addSubview(label)
        let g = self.layoutMarginsGuide
        NSLayoutConstraint.activate([
            // constrain label to the self's margins guide
            label.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            label.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            label.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
        ])
        // this avoids auto-layout complaints
        let c = label.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0)
        c.priority = UILayoutPriority(rawValue: 999)
        c.isActive = true
        
        backgroundColor = .red
        label.backgroundColor = .yellow
    }
    
}

示例表視圖控制器

class DynamicHeaderTableViewController: UITableViewController {
    
    var theData: [String] = []
    
    let myHeaderView = MyTableHeaderView()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 10 rows with 2-to-5 lines per row
        for i in 1...10 {
            let s = "This is row \(i)"
            let n = Int.random(in: 1...4)
            let a = (1...n).map { "Line \($0)" }
            theData.append(s + "\n" + a.joined(separator: "\n"))
        }
        
        tableView.register(MultilineCell.self, forCellReuseIdentifier: "cell")
        
        myHeaderView.label.text = "Select a row..."
        tableView.tableHeaderView = myHeaderView
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        tableView.sizeHeaderToFit()
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return theData.count
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let c = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MultilineCell
        c.label.text = theData[indexPath.row]
        return c
    }
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        myHeaderView.label.text = theData[indexPath.row]
        tableView.sizeHeaderToFit()
    }
}

上面的代碼將生成 10 行,每行 2 到 5 行。 didSelectRowAt我們將使用行中的文本更新表視圖標題。

首次啟動時的結果:

在此處輸入圖片說明

選擇“第 2 行”后:

在此處輸入圖片說明

選擇“第 3 行”后:

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM