"fits"(ala "sizeToFit")其动态单元格内容大小的 TableView。然后嵌套在一个也是 "sized to fit" 的父 UIView 中

A TableView that "fits" (ala "sizeToFit") its dynamic cell's content size. Then nested in a parent UIView that is also "sized to fit"

我不确定我是否以最佳方式处理这个问题。

(1) 首先,我想要一个 tableView 具有任意数量的单元格,其动态单元格高度会变化(基于来自 Web 服务器的内容,无法提前计算)。但我希望 tableView 的高度只增加到适合所有单元格内容的高度(不是更高或更短)。此 table 视图将不可滚动(它的父视图是可滚动的)。

(2) 然后,我希望 tableView 嵌套在父 UIView 中。

我大部分时间 (1) 都在工作,尽管我不知道我的方法是最优的还是老套的。但我绝对没有 (2) 工作:(

(下图)Turqoise 视图是 table 视图的父视图。单元格(红色)和 table 大小(白色)正确,但父视图比应有的短。

我的代码更改后,我遇到了相反的问题。父级高度增长到大约合适的高度,但是 tableView 被砍掉了。

这是代码更改:

查看层次结构:

如果我不尝试将 tableView 放在父 UIView 中,table "size to fits" 恰到好处:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var tableView: UITableView!
    @IBOutlet var tableViewHeightConstraint: NSLayoutConstraint!

    @IBOutlet var parentView: UIView!

    @IBOutlet var parentViewHeightConstraint: NSLayoutConstraint!

    let data = ["this is a short line.",
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Excepteur sint. deserunt mollit anim id est laborum.",
                "another short line.",
                "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam  explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia."
                ]

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 50

    } // viewDiDload
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // If I add this new frame for the table's parent view,
        // the table view height gets chopped off. See 3 lines below
        var newFrameForParent = self.parentView.frame
        newFrameForParent.size.height = self.tableView.contentSize.height
        self.parentView.frame = newFrameForParent
        // But if I comment out the above 3 lines, the table view
        // height is fine (table height fits actual dynamic content size)
        // but the table's parent view is shorter than the table view

        var newFrame = self.tableView.frame
        newFrame.size.height = self.tableView.contentSize.height
        self.tableView.frame = newFrame

        print("viewDidAppear: tableView contentSize w: \(tableView.contentSize.width) h: \(tableView.contentSize.height)")

    } // viewDidAppear

    override func viewWillLayoutSubviews() {
        super.updateViewConstraints()
        self.tableViewHeightConstraint.constant = self.tableView.contentSize.height
        //self.parentViewHeightConstraint.constant = self.tableView.contentSize.height + 20
        print("viewWillLayoutSubviews: tableView contentSize w: \(tableView.contentSize.width) h: \(tableView.contentSize.height)")
    } // viewWillLayoutSubviews
    override func viewWillAppear(_ animated: Bool) {
        //tableView.sizeToFit()
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CellID", for: indexPath) as! CustomCell
        cell.cellLabel?.text = data[indexPath.row]

        print("cell \(indexPath.row) height is: \(cell.frame.height)")

        return cell
    }

}

完整的代码库在这里:https://github.com/jayliew/UITableViewSizeToFitDynamicHeightCells/tree/master/TableViewFitContent

我不确定我需要知道什么,我不知道,但我怀疑它与完全理解视图的布局方式、AutoLayout 如何发挥作用以及 viewController viewWillAppear、viewWillLayoutSubviews 等生命周期(每个阶段如何影响视图的布局,有或没有 AutoLayout)。我不只是想解决这个问题,而是更全面地了解架构,如果有人能指出正确的方向,我将不胜感激。

回答我自己的问题:

我学到的教训是不要将 AutoLayout 与手动创建框架和更改视图混合使用这些框架。

我了解到我必须首先人为地将 tableView 设置为一个巨大的高度,例如1000,这样动态单元格将在 table 上 "visible"。然后我只能遍历所有这些单元格,获取框架高度,手动将它们全部相加,然后在 tableView 上设置 AutoLayout 高度约束常量等于所有单元格高度的总和。

此外,上述内容必须在 viewDidAppear() 内部发生

就是这样!此处示例代码:https://github.com/jayliew/UITableViewSizeToFitDynamicHeightCells

感谢@ddustin Github