“适合”(也称为“sizeToFit”)其动态单元格内容大小的 TableView。然后嵌套在同样“大小适合”的父 UIView 中
Posted
技术标签:
【中文标题】“适合”(也称为“sizeToFit”)其动态单元格内容大小的 TableView。然后嵌套在同样“大小适合”的父 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" 【发布时间】:2017-07-08 16:44:21 【问题描述】:我不确定我是否以最优化的方式处理这个问题。
(1) 首先,我想要一个具有任意数量单元格的 tableView,其动态单元格高度会发生变化(基于来自 Web 服务器的内容,无法提前计算)。但我希望 tableView 的高度只增长到适合所有单元格的内容(不是更高或更短)。此表视图将不可滚动(它将是父级的父级视图)。
(2) 然后,我希望 tableView 嵌套在父 UIView 中。
虽然我不知道我的方法是最优的还是骇人听闻的,但我大部分时间都在 (1) 工作。但我绝对没有(2)工作:(
(下图)Turqoise 视图是表视图的父级。单元格(红色)和表格大小(白色)正确,但父视图比应有的短。
更改代码后,我遇到了相反的问题。父级高度增长到大约正确的高度,但 tableView 被砍掉了。
这是代码更改:
查看层次结构:
如果我不尝试将 tableView 放在父 UIView 中,表格“大小适合”恰到好处:
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、等等(每个阶段如何影响视图的布局,有或没有自动布局)。我不只是想解决这个问题,而是更全面地了解架构,如果有人能指出我正确的方向,我将不胜感激。
【问题讨论】:
【参考方案1】:回答我自己的问题:
我学到的教训是不要将 AutoLayout 与手动创建框架和更改视图以使用这些框架相结合。
我了解到我必须首先人为地将 tableView 设置为一个巨大的高度,例如1000,以便动态单元格在表格上“可见”。然后我只能遍历所有这些单元格,获取框架高度,手动将它们全部加起来,然后在 tableView 上设置 AutoLayout 高度约束的常量,使其等于所有单元格高度的总和。
另外,上面的事情必须发生在 viewDidAppear() 中
就是这样!示例代码:https://github.com/jayliew/UITableViewSizeToFitDynamicHeightCells
感谢 Github 上的@ddustin
【讨论】:
以上是关于“适合”(也称为“sizeToFit”)其动态单元格内容大小的 TableView。然后嵌套在同样“大小适合”的父 UIView 中的主要内容,如果未能解决你的问题,请参考以下文章
sizeToFit() 返回错误的高度 - 需要在 heightForRow 中查找单元格宽度
Swift:在 sizetofit 之后无法获得标题单元格标签的正确高度