ios - 自定尺寸单元格高度变化导致跳跃动画
问题描述
我已经使用 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
任何形式的帮助表示赞赏。谢谢。
解决方案
我的解决方案是添加动态估计行高。我认为这是 UIKit 的错误。不会出现 iOS 13 问题。
首先,您需要添加属性estimateRowHeightStorage
以通过 indexpath 存储估计高度
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
}
推荐阅读
- laravel - Pikaday 在 laravel livewire 中没有定义
- node.js - 没有用户的图形 api 请求令牌
- xamarin.forms - XAMARIN 通过 PRISM 在 Tabpage 中选择选项卡
- ubuntu - Ubuntu 服务器安装在目标中的 curtin 命令处停止
- python - 使用产品和变体填充电子商务表
- javascript - 如何在mousemove上获取屏幕上像素的颜色?
- linux - 在 Linux Mint 20.1 / Ubuntu 20.04 上安装/卸载 Docker 后网络连接断开
- google-apps-script - 我拥有几个带有按钮激活脚本的 GS 电子表格。我可以授予用户使用它们的权限,而这些用户不会牺牲他们的安全性吗?
- flutter - NestedScrollView 的颤振问题
- ios - 计算属性重复