【问题标题】:How to dynamically resize table view header?如何动态调整表格视图标题的大小?
【发布时间】:2020-10-13 15:42:48
【问题描述】:

当人们点击加载更多时,我想动态调整表格视图标题的大小。发生的情况是,当人们单击加载更多时,新内容会添加到表格视图标题中,因此高度会发生变化。我事先不知道新的高度。

我该怎么做?我现在做的是当人们点击“加载更多”时,我执行下面的代码。

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

我可以在上面的代码中添加什么来动态调整表格视图标题的大小?

【问题讨论】:

  • 你想要 tableheaderView 或 table section header 吗?

标签: ios swift


【解决方案1】:

只需使用约束,您就可以为它们设置动画。您不必为此重新加载整个表格视图。你可以保持对标题的弱引用并改变它的状态,如果按下更多,动画约束,如果它是你想要适应的文本,使用 StackView 并且只需添加/删除 UILabel 到堆栈视图,它应该可以完美地工作。

【讨论】:

【解决方案2】:

自动布局不会自动更新表头视图的大小,因此我们需要“手动”进行。

我们可以使用这个扩展来帮助:

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行”后:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-05
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    相关资源
    最近更新 更多