ios - 如何允许屏幕外 UITableViewCell 下推内容偏移?
问题描述
我有一个 UITableView,其中包含一堆单元格。
如果用户单击第二个单元格,则第一个单元格应该设置动画并显着扩展其高度,并将所有其他单元格向下推,使用户的滚动位置保持在同一位置。当两个单元格都在屏幕上时,我的代码 100% 正确工作。UITableView 的 contentSize 显着增长,contentOffset 没有变化。
但是,如果用户向下滚动以便只有第二个单元格可见,当他们点击它时,第一个单元格会展开到屏幕外,用户什么也不会发生。
UITableView 的 contentSize 不变,contentOffset 也不变。一旦用户稍微向上滚动并看到展开单元格的底部,contentSize 和 contentOffset 就会更新以反映第一个单元格确实要大得多的事实(但从用户的角度来看没有任何变化)
heightForRowAtIndexPath
在展开前后调用单元格的索引路径会返回预期值。
我的代码有很多事情要做,但是应该为扩展设置动画的主要部分在这里:
UIView animateWithDuration:0.3
animations:^{
performSelectorOnMainThread(@selector(updateItemHeights:), withObject: nil, waitUntilDone: YES)
}
completion:^(BOOL finished){}]
以及updateItemHeights的实现:
beginUpdates
endUpdates
self.contentSize = sizeThatFits([contentSize.width, CGFLOAT_MAX])
似乎 iOS 试图通过允许上方的单元格展开来使用户保持在当前上下文中。
如何让屏幕外单元格将其他单元格向下推?
解决方案
感谢 table view dequeue 系统,当一个单元格不可见时,它不会被加载。因此,如果表格视图在屏幕上不可见,则表格视图不会为更改设置动画。
我在这里看到 2 个选项:
在更新其高度之前滚动到动画单元格
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let animatedIndexPath = ...
let visibleRows = tableView.indexPathsForVisibleRows ?? []
if visibleRows.contains(animatedIndexPath) {
self.tableView.reloadRows(at: [animatedIndexPath], with: .automatic)
} else {
UIView.animate(withDuration: 0.3, animations: {
self.tableView.scrollToRow(at: animatedIndexPath, at: .none, animated: false)
}) { _ in
self.tableView.reloadRows(at: [animatedIndexPath], with: .automatic)
}
}
}
更新单元格后调整内容偏移量
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let animatedIndexPath = ...
let visibleRows = tableView.indexPathsForVisibleRows ?? []
if visibleRows.contains(animatedIndexPath) {
self.tableView.reloadRows(at: [animatedIndexPath], with: .automatic)
} else {
let offset = tableView.contentOffset
tableView.reloadData()
tableView.layoutIfNeeded() // forces the new offset computation
tableView.setContentOffset(offset, animated: true)
}
}
(由于表格视图动态高度计算,您可能会遇到一些问题,禁用它tableView.estimatedRowHeight = 0
)
推荐阅读
- simulation - 执行模拟后如何从最小二乘估计方法中找到估计值和偏差
- python - ModelForm PasswordInput 的 Django 密码格式无效
- javascript - 使用 Codecept 和 Puppeteer 测试一个带有 role="combobox" 的 div
- postgresql - 如何在ansible中迭代环境变量?
- php - 如何确保消息不会发送到数据库中数据不存在的电话号码?
- google-cloud-platform - Google Autopilot 集群:不可调度的 pod
- c - PCRE2_CODE_UNIT_WIDTH 不是 8
- javascript - 在正文中的标题旁边显示百分比
- java - 如何使用 XJC 插件在 SOAP 响应中自定义命名空间前缀
- r - 一次选择列表中的一项