我有一个 UITableViewCell
,其中包含顶部的 UICollectionView
和底部的 UITableView
。这个想法是,将在内部 UITableView
中创建动态数量的单元格,并且包含两个 subview 的父 UITableViewCell
将按比例增加其高度。
我正在尝试利用 UITableViewCell
的 estimatedRowHeight
+ UITableViewAutomaticDimention
功能,该功能将允许单元格高度动态增加。但是,它不起作用。它从 View 中完全删除了嵌入的 UITableView
。
我没有做出任何限制所包含的 UITableView
高度的约束,所以我不确定为什么它不起作用。
下面是尝试动态调整大小的 UITableViewCell
的实现:
class OverviewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Enclosed Table View Example"
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 325 // Height for inner table view with 1 cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 45
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "appHeaderCell") as! AppHeaderCell
return cell
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "appCell", for: indexPath) as! AppCell
return cell
}
}
我唯一的猜测是约束 bottom = Inner Table View.bottom + 7
导致了这个问题,但是当这个约束被删除时,整个 View 就会崩溃。
如何才能使复杂的外部 UITableViewCell
根据嵌入 UITableView
中的单元格数量动态调整高度?
最佳答案
虽然这看起来是个好主意,但将 UITableViewAutomaticDimension
与 estimatedRowHeight
结合使用并不适合在这样的场景中使用,在这种情况下,我们有通用的 TableView 单元格内的内容。利用 heightForRowAt
方法,您可以在将表格居中之前计算每个单元格的大小。
一旦我们知道内部表格中有多少个单元格,您就需要创建一个数组,其元素对应于内部单元格的数量,最终确定外部单元格的高度,因为所有其他内容都是恒定的。
let cellListFromData: [CGFloat] = [3, 1, 4]
这个数组将为我们提供外部 TableView 中的部分数量:
func numberOfSections(in tableView: UITableView) -> Int {
return cellListFromData.count
}
我们将通过以下方式将此数组中的每个元素转换为单元格高度:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let prototypeCell = tableView.dequeueReusableCell(withIdentifier: "appCell") as! AppCell
let baseHeight = betweenCellSpacing + prototypeCell.innerCollectionView.contentSize.height + prototypeCell.innerTableView.sectionHeaderHeight + outerTableView.sectionHeaderHeight
let dynamicHeight = prototypeCell.innerTableView.contentSize.height - prototypeCell.innerTableView.sectionHeaderHeight
return baseHeight + (dynamicHeight * cellListFromData[indexPath.section])
}
也就是说,在 heightForRowAt
方法内部,我们将不会在结果 View 中使用的原型(prototype)单元出队(因为 dequeueReusableCell
未在 内部调用)在本例中为 cellForRowAt
)。我们使用此原型(prototype)单元来提取有关单元内容的恒定和动态信息。 baseHeight
是单元格所有常量元素的累积高度(加上单元格之间的间距),dynamicHeight
是内部 UITableViewCell< 的高度
。每个单元格的高度将变为 baseHeight +dynamicHeight * cellListFromData[indexPath.section]
。
接下来,我们将 numberOfCells
变量添加到自定义单元格的类中,并在主 TableView 中的 cellForRowAt
方法中进行设置:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "appCell", for: indexPath) as! AppCell
cell.numberOfCells = Int(cellListFromData[indexPath.section])
cell.innerTableView.reloadData()
return cell
}
numberOfCells
的设置与我们用于获取单元格高度的 cellListFromData
相同。此外,在设置单元格数量后,在内部表格 View 上调用 reloadData()
至关重要,以便我们在 UI 中看到更新。
完整代码如下:
class OverviewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var outerTableView: UITableView!
let cellSpacing: CGFloat = 25
let data: [CGFloat] = [3, 1, 4]
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in tableView: UITableView) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let prototypeCell = tableView.dequeueReusableCell(withIdentifier: "appCell") as! AppCell
let baseHeight = cellSpacing + prototypeCell.innerCollectionView.contentSize.height + prototypeCell.innerTableView.sectionHeaderHeight + outerTableView.sectionHeaderHeight
let dynamicHeight = prototypeCell.innerTableView.contentSize.height - prototypeCell.innerTableView.sectionHeaderHeight
return baseHeight + (dynamicHeight * data[indexPath.section])
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "appCell", for: indexPath) as! AppCell
cell.numberOfCells = Int(data[indexPath.section])
cell.innerTableView.reloadData()
return cell
}
}
class AppCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var innerCollectionView: UICollectionView!
@IBOutlet weak var innerTableView: UITableView!
var numberOfCells: Int = 0
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberOfCells
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "featureHeaderCell") as! BuildHeaderCell
return cell
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "innerCell", for: indexPath) as! InnerCell
return cell
}
}
此处不包含与配置内部 Collection View 相关的方法,因为它与问题无关。
关于iOS/swift : Dynamic UITableViewCell row height with embedded UITableView not working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44839030/