无法扩展 UITableView

Posted

技术标签:

【中文标题】无法扩展 UITableView【英文标题】:Trouble Expanding UITableView 【发布时间】:2020-01-16 00:21:46 【问题描述】:

目标和背景

我正在尝试使用this tutorial 创建一个可扩展的 UITableView。但是,我希望表格更新其容器的高度,以便新高度与内容匹配。问题是这会在表格的最后一个标题(部分)上产生视觉故障 - 但仅在第一次执行动画时。

这就是它的样子:link

我的想法是,随着表格展开隐藏的单元格,最后一行被推到视野之外。所以当我更新视图的高度时,它必须重新绘制最后一个单元格(注意重新加载时的颜色变化)。不过,我不确定奇怪的滑入式动画来自哪里。


问题

我将如何消除此故障或更好地完成此任务?


代码

这是我的层次结构:

+-- ParentVC
|   +-- ParentView
|   |   +-- CustomTableVC's View
|   |   |   +-- Custom UITable

(CustomTableVC is a child of ParentVC)

这就是我重新加载点击部分并设置新高度的方式

// === CustomTableVC === //
func toggleSection(_ header: PTTableHeader, section: Int) 

       ...

       // Reload the section with a drop-down animation
       table.reloadSections(NSIndexSet(index: section) as IndexSet, with: .automatic)

       // Update the height of the container view
       preferredContentSize.height = table.contentSize.height


// Height for section headers and rows: 44 (including estimated)

这是父级的更新方式:

// === ParentVC === //
override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) 
       super.preferredContentSizeDidChange(forChildContentContainer: container)
       if let child = container as? PTTable 
              customTableVC.view.layoutIfNeeded()
              customTableViewHeightAnchor.constant = child.preferredContentSize.height
              UIView.animate(withDuration: 3, animations: 
                     view.layoutIfNeeded()
              )
       
       // Height anchor starts at parentView's height / 3 because 
       //  I'm not sure how to make it match the table's contentSize from the get-go

删除view.layoutIfNeeded() 会导致最后一部分不执行滑入动画,但仍会执行glitch out。


在 iPhone 11 Pro(模拟器)上运行。

【问题讨论】:

"我希望表格更新其容器的高度,以便新的高度与内容相匹配。"只是想知道为什么您尝试让表格与内容高度匹配。它不会自己处理吗? @Kanongata 该表知道其新的所需高度,但由于 CustomTableVC 的视图小于该高度,它没有增长空间。所以它最终会启用滚动。 很公平。查看您的 2 个 gif,在展开单元格之前和折叠单元格之后,内容高度似乎不一致。折叠单元格后,内容高度大于初始状态。如果从那时起您对这种行为感到满意 - 可以尝试最初设置内容高度以匹配单元格展开然后折叠后的高度。 @Kanongata 我对其进行了测试,这似乎解决了单元格重新加载问题,但这意味着如果我有足够的隐藏单元格,我将需要将初始高度设置得非常大:/ 我能想到的最佳选择是为展开和折叠的单元格设置 2 个不同的重用标识符。因此,只要一个单元格被折叠,就不需要绘制所有这些 UIView。如果它被扩展,你可以用 tableView 更新来动画化这个变化。 【参考方案1】:

反射

我让它工作了。一旦我弄清楚了,这个技巧实际上非常简单。我仍然认为这有点令人费解/有异味,但它适用于我的目的以及我以前使用的method。


解决方案

基本上,我设置了preferredContentSize 之前我重新加载这些部分。这会提醒 ParentVC 在实际发生任何变化之前开始制作动画。这意味着表格现在有空间将底部移动到其中而无需重新加载它。


代码

// === CustomTableVC === //
func toggleSection(_ header: PTTableHeader, section: Int) 

       ...

       // Predict the height of the table BEFORE reloading it
       predictHeight(section: section, willExpand: isExpanding) // Change isExpanding with whatever Bool is tracking the expand/collapse state of the section

       // THEN reload the section with a drop-down animation
       table.reloadSections(NSIndexSet(index: section) as IndexSet, with: .automatic)

       // Optionally do the above with an animation using UIView.animate() or UIView.transition()

       // And FINALLY update the height of the container view
       // This one is probably optional, but it will be more exact depending on what methods you use to predict the height in predictHeight()
       preferredContentSize.height = table.contentSize.height


func predictHeight(section: Int, willExpand: Bool) 
        // Get the heights of all the known headers/footers/rows
        let tableSectionsHeight = CGFloat(table.numberOfSections) * (table.estimatedSectionHeaderHeight + table.sectionFooterHeight)
        let tableCellsHeight = CGFloat(table.visibleCells.count) * table.estimatedRowHeight

        // Calculate the height of the section being expanded/collapsed
        // With the method I used, I can't just do table.numberOfRows(inSection: Int) since expanding/collapsing is essentially just adding/removing those rows
        // Instead I need to store a reference to the number of rows per section and access it via that array, object, etc.
        let sectionContentHeight = willExpand ? CGFloat(rowCounts[section]) * table.estimatedRowHeight : 0 // 0 if collapsing

        // Set the preferredContentSize so that the ParentVC picks it up 
        preferredContentSize.height = tableSectionsHeight + tableCellsHeight + sectionContentHeight
    

【讨论】:

以上是关于无法扩展 UITableView的主要内容,如果未能解决你的问题,请参考以下文章

iOS 扩展:无法更改图标

无法设置操作扩展图标,改为灰色图标

无法扩展:TailwindCSS 变体:

无法在局部视图中使用扩展方法

Laravel 无法扩展默认刀片模板

无法启用 mysqli 扩展 - PHP 7.1.12,无法连接到数据库