iOS UITableViewController 单元格在第一次更改时调整单元格高度后跳出位置
iOS UITableViewController cells jumping out of place after resizing cell heights on first change
更新:看起来 tableView.estimatedRowHeight
设置与问题有某种关系,因为问题的方差随着数字的变化而变化,将其设置为 9999 会使它 "go away" 但是看起来超级hacky。 9999 也打破了我打算在 show/hide 上做的动画。 9999 还破坏了滚动条的功能。有关更多详细信息和完整上下文,请参阅下面的讨论主题。
我有一个包含两个 Container Views
的视图控制器。每个容器视图都包含一个 UITableView
控制器。它们垂直放置,每个都占据整个高度。
右侧的容器宽度为 100,从屏幕开始,尾随约束设置为 -100,这允许另一个容器最初填满整个屏幕。
左侧的 table 使用 UITableViewAutomaticDimension
自动调整单元格高度,因为当显示隐藏视图时,两行上的某些文本可能需要换行。
当我将约束更改为 0 并显示视图时,如果我不在列表的顶部,而不是扩展屏幕上可见的内容,它似乎在扩展所有内容,从而推动了原来的内容在屏幕上向下,比它应该走的更远。
但奇怪的是,后续 expand/collapses 是否按预期工作,仅调整可见部分。
我附上了一个视频来展示这个问题,我只是想把事情联系起来,让大小调整工作,正确视图中的内容最终会有所不同。
以下是视频中发生的事情
- 我从列表的顶部 expand/collapse 并且按预期工作
- 我滚动到列表的中间并展开,但我的内容被向下推得比它应该的更深。
- 然后我再次折叠并展开它,这次它留在原处,因为可见屏幕上的尺寸没有改变。
无论我在列表中往下走多远,相同的行为都会发生,越往下越糟。
我现在正在按这样的按钮调整约束。
if self.timeContainerConstraint.constant == 0 {
self.timeContainerConstraint.constant = -90.0
} else {
self.timeContainerConstraint.constant = 0.0
}
有谁知道为什么我第一次向下滚动列表并展开时内容会跳转,但在后续尝试时不会跳转?
由于单元格高度可变,table视图在其框架发生变化时无法正确计算滚动偏移量。它必须依赖估计的行高,但是因为你有一个固定的值,所以当前滚动位置的单元格越多'above',估计值和实际值之间的误差就越大。
我能够通过缓存单元格高度来解决这个问题,以便使用 estimatedHeightForRowAt:
return 更准确的估计高度
var cellHeights = [IndexPath:CGFloat]()
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let frame = tableView.rectForRow(at: indexPath)
self.cellHeights[indexPath] = frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return self.cellHeights[indexPath] ?? 140.0
}
使用这种方法,侧边栏的扩展和收缩不会影响 table 的位置。我能够为约束变化设置动画以获得平滑的显示效果,而 table 没有 'jump',即使 table 在边栏打开时滚动。
我的示例项目是here
更新:看起来 tableView.estimatedRowHeight
设置与问题有某种关系,因为问题的方差随着数字的变化而变化,将其设置为 9999 会使它 "go away" 但是看起来超级hacky。 9999 也打破了我打算在 show/hide 上做的动画。 9999 还破坏了滚动条的功能。有关更多详细信息和完整上下文,请参阅下面的讨论主题。
我有一个包含两个 Container Views
的视图控制器。每个容器视图都包含一个 UITableView
控制器。它们垂直放置,每个都占据整个高度。
右侧的容器宽度为 100,从屏幕开始,尾随约束设置为 -100,这允许另一个容器最初填满整个屏幕。
左侧的 table 使用 UITableViewAutomaticDimension
自动调整单元格高度,因为当显示隐藏视图时,两行上的某些文本可能需要换行。
当我将约束更改为 0 并显示视图时,如果我不在列表的顶部,而不是扩展屏幕上可见的内容,它似乎在扩展所有内容,从而推动了原来的内容在屏幕上向下,比它应该走的更远。
但奇怪的是,后续 expand/collapses 是否按预期工作,仅调整可见部分。
我附上了一个视频来展示这个问题,我只是想把事情联系起来,让大小调整工作,正确视图中的内容最终会有所不同。
以下是视频中发生的事情
- 我从列表的顶部 expand/collapse 并且按预期工作
- 我滚动到列表的中间并展开,但我的内容被向下推得比它应该的更深。
- 然后我再次折叠并展开它,这次它留在原处,因为可见屏幕上的尺寸没有改变。
无论我在列表中往下走多远,相同的行为都会发生,越往下越糟。
我现在正在按这样的按钮调整约束。
if self.timeContainerConstraint.constant == 0 {
self.timeContainerConstraint.constant = -90.0
} else {
self.timeContainerConstraint.constant = 0.0
}
有谁知道为什么我第一次向下滚动列表并展开时内容会跳转,但在后续尝试时不会跳转?
由于单元格高度可变,table视图在其框架发生变化时无法正确计算滚动偏移量。它必须依赖估计的行高,但是因为你有一个固定的值,所以当前滚动位置的单元格越多'above',估计值和实际值之间的误差就越大。
我能够通过缓存单元格高度来解决这个问题,以便使用 estimatedHeightForRowAt:
var cellHeights = [IndexPath:CGFloat]()
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let frame = tableView.rectForRow(at: indexPath)
self.cellHeights[indexPath] = frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return self.cellHeights[indexPath] ?? 140.0
}
使用这种方法,侧边栏的扩展和收缩不会影响 table 的位置。我能够为约束变化设置动画以获得平滑的显示效果,而 table 没有 'jump',即使 table 在边栏打开时滚动。
我的示例项目是here