自定尺寸单元格高度变化导致跳跃动画
Posted
技术标签:
【中文标题】自定尺寸单元格高度变化导致跳跃动画【英文标题】:Self sizing cells height change causes jumping animation 【发布时间】:2019-08-18 09:07:56 【问题描述】:我已经使用 Autolayout 设置了一个带有动态高度单元格的表格视图,即 UITableView.automaticDimension。这工作正常。现在我想要实现的是改变单元格的高度并为其设置动画。问题是当我更改单元格高度并为其设置动画时,动画会奇怪地跳跃。仅当我向下滚动一点然后展开/折叠单元格时才会发生跳转。 我有一个简单的表格视图单元格。它有一个标签和一个具有固定高度约束的空 UIView。当我想折叠/展开单元格时,我只需将该高度约束的常数更改为 0 或 300。
我在网上尝试了许多可折叠的 tableview 示例。他们都有这个问题。 https://github.com/Ramotion/folding-cell 是一个例外,但它使用固定高度的单元格。
我已经尝试了很多选项来为单元格高度变化设置动画。
1-> 在 didSelectRow 上,我更改了高度约束并调用 tableview beginUpdate 和 endUpdates。不能解决跳转问题。
2-> 更改我的模型并调用 tableView.reloadRows。不能解决跳转问题。
这是我的表格视图单元设置的屏幕截图。 https://drive.google.com/open?id=12nba6cwRszxRlaSA-IhrX3X_vLZ4AWxy
此问题的视频链接: https://drive.google.com/open?id=19Xmc0PMXT0EuHTJeeGHm4M5aPoChAtf3
override func viewDidLoad()
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.estimatedRowHeight = 50
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedSectionHeaderHeight = 0
tableView.estimatedSectionFooterHeight = 0
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! OuterTableViewCell
let height: CGFloat = isCellExpanded[indexPath.row] ? 300 : 0
cell.labelText.text = "Cell Number: \(indexPath.row + 1)"
cell.buttonExpansionToggle.setImage(UIImage(named: isCellExpanded[indexPath.row] ? "arrow-down" : "arrow-right"),
for: .normal)
cell.viewContainerHeight.constant = height
return cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
isCellExpanded[indexPath.row] = !isCellExpanded[indexPath.row]
tableView.reloadRows(at: [indexPath], with: .automatic)
didSelectRow 的另一种形式:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
guard let cell = tableView.cellForRow(at: indexPath) as? OuterTableViewCell else return
isCellExpanded[indexPath.row] = !isCellExpanded[indexPath.row]
let height: CGFloat = self.isCellExpanded[indexPath.row] ? 300 : 0
cell.viewContainerHeight.constant = height
cell.layoutIfNeeded()
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations:
tableView.beginUpdates()
tableView.endUpdates()
// fix https://github.com/Ramotion/folding-cell/issues/169
if cell.frame.maxY > tableView.frame.maxY
tableView.scrollToRow(at: indexPath, at: UITableView.ScrollPosition.bottom, animated: true)
, completion: nil)
我也尝试在动画块之外调用 beginUpdates() 和 endUpdates(),但问题仍然存在。
我希望动画流畅。希望有人可以提供帮助。如果有人可以在 github 上设置一个简单的演示项目,那就太棒了。
演示项目链接:https://gitlab.com/FahadMasoodP/nested-tableviews
感谢任何形式的帮助。谢谢。
【问题讨论】:
你能把你的示例项目放上去吗? @ThanhVu 我现在已经包含了示例项目的 gitlab 链接 gitlab.com/FahadMasoodP/nested-tableviews 能否请您在表格委托方法中提供高度。而在 didSelect 方法中只是重新加载特定的行。看看进展如何? 根据我的经验,请不要使用估计的行高,而是使用高度方法。 @JayrajVala 我不能使用固定高度。使用 Autolayout 自动计算单元格大小,正如您在 viewDidLoad 中看到的那样,我已将行高设置为 UITableView.automaticDimension 【参考方案1】:我的解决方案是添加动态估计行高。我认为这是 UIKit 的错误。不会出现 ios 13 问题。
首先,您需要添加属性estimateRowHeightStorage
以通过索引路径存储估计高度
var estimateRowHeightStorage: [IndexPath:CGFloat] = [:]
其次,您需要存储当前单元格的高度以备后用
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
estimateRowHeightStorage[indexPath] = cell.frame.size.height
Final,您使用estimateRowHeightStorage
设置估计行高。
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
if estimateRowHeightStorage[indexPath] != nil
return estimateRowHeightStorage[indexPath]!
return 50
跑步和感受。
我确实在您的情况下找到了新的解决方案。如果在展开时硬固定高度。只需要改变一些东西。
将以上代码全部替换为estimatedHeightForRowAt
函数
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
let height: CGFloat = isCellExpanded[indexPath.row] ? 373 : 73
return height
【讨论】:
感谢您的回答。我尝试了这个解决方案,它似乎适用于前几个单元格,但后来我发现问题仍然存在。我已经在 gitlab 上更新了这个项目,所以你可以检查一下。如果你打开最后 5-6 个单元格,然后从底部开始一个一个地关闭,你会发现问题仍然存在。 虽然单元格大小不会固定/预先计算,但我尝试了您更新的解决方案。不工作。这是你更新后的视频drive.google.com/open?id=1EsKr97ZTA1z2V_kmCBsr7bNi-V-cSlje 我在真机上试过了,问题依旧以上是关于自定尺寸单元格高度变化导致跳跃动画的主要内容,如果未能解决你的问题,请参考以下文章
具有动态单元格高度的 UITableView 的 reloadData() 导致跳跃滚动
当上边距不完全可见时,UITableView 单元格展开动画会发生变化