UITableView 动态单元格高度在过渡或旋转时中断
Posted
技术标签:
【中文标题】UITableView 动态单元格高度在过渡或旋转时中断【英文标题】:UITableView dynamic cell height breaks on transition or rotation 【发布时间】:2014-11-06 07:40:34 【问题描述】:目前我正在处理快速和动态的表格单元格高度。我在xcode6.1上为ios8.1开发了一个简单的app:https://github.com/ArtworkAD/DynamicCellTest
因此,为了实现与单元格内容一致的单元格高度,我执行以下操作:
在情节提要中将标签行设置为 0 将标签字体设置为系统 为单元格中的标签设置约束 添加self.tableView.rowHeight = UITableViewAutomaticDimension
不要覆盖heightForRowAtIndex
方法
需要最少的代码:
class MyTableViewController: UITableViewController
var entries:Array<String> = [String]()
override func viewDidLoad()
super.viewDidLoad()
//create dummy content
var i = 0
while i < 10
entries.append("\(i) Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor")
entries.append("\(i+1) Lorem ipsum dolor sit amet")
i = i + 2;
self.tableView.rowHeight = UITableViewAutomaticDimension
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return self.entries.count
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = self.tableView.dequeueReusableCellWithIdentifier("basic_cell", forIndexPath: indexPath) as UITableViewCell
var label = cell.viewWithTag(13)
if let unwrappedLabel = label as? UILabel
unwrappedLabel.text = self.entries[indexPath.row]
return cell
左图显示了上述代码的结果。单元格高度随着标签的内容而增长,一切都很好。但是,当您单击显示指示器到详细视图并再次返回时,您会得到正确的图像。为什么会这样??
这个问题的一个不好的解决方案是重写这个方法:
override func viewWillDisappear(animated: Bool)
super.viewWillDisappear(animated)
self.tableView.reloadData()
override func viewDidAppear(animated: Bool)
super.viewDidAppear(animated)
self.tableView.reloadData()
override func viewDidDisappear(animated: Bool)
super.viewDidDisappear(animated)
self.tableView.reloadData()
这样就解决了上面的问题,但是这个解决方法好像不对吧?它的一个副作用是,当self.tableView.reloadData()
被调用时,表格视图端口会跳转到第一个看起来不太好的单元格。
有人知道我做错了什么吗?随意克隆我的 repo https://github.com/ArtworkAD/DynamicCellTest 并进行测试。
【问题讨论】:
我认为willTransitionToTraitCollection:withTransitionCoordinator:
是重新加载表格视图数据的更好地方。
@VitoZiv 问题依然存在。
这似乎是个问题。找到这个openradar.appspot.com/17799811
您是否检查过是否真的加载了您布局的 UITableViewCell 的实例?可能是数据源只是分配了一个标准 UITableViewCell 因此 numberOfLines 设置为 1 和 truncateTail。
它通过在返回单元格之前添加 cell.setNeedsDisplay() 和 cell.setNeedsLayout() 来工作。
【参考方案1】:
添加这个似乎可以解决旋转问题。
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
self.tableView.estimatedRowHeight = 36.5
但是,我有另一种情况,单元格中有 4 个标签,也有相同的旋转问题,添加这还不够,我最终用重新加载可见单元格替换了 self.tableView.estimatedRowHeight = 36.5
。
【讨论】:
解决方案不是很理想,希望有人能提出一个更优雅的方案。 这里有同样的问题,但没有用。您能解释一下如何重新加载可见单元格吗?谢谢,西德。 @sidd,[tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
唯一对我有用的是重新加载可见单元格。
这行得通。这么多小时,我所要做的就是这样吗? RIP【参考方案2】:
我刚刚通过在UITableViewDelegate
对象中覆盖tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath)
解决了这个问题。
func tableView(tableView: UITableView,
estimatedHeightForRowAtIndexPath indexPath: NSIndexPath)
-> CGFloat
return 200
更改确切的返回值显然没有效果。细胞总是正确地自我调整大小。我不知道为什么提供估计的高度会导致自动布局启动,但确实如此。 iOS 8.1.2,Xcode 6.1。
【讨论】:
【参考方案3】:该链接很好地解释了需要做什么。
Using Auto Layout in UITableView for dynamic cell layouts & variable row heights
对于您的具体问题,您缺少两行代码。
在viewDidLoad
下你的tableView.rowHeight
添加self.tableView.estimatedRowHeight = 64
上面将允许 tableView 为屏幕外单元格分配估计的高度值以提高性能,它还计算滚动条高度。
主要问题是您在cellForRowAtIndexPath
中缺少unwrappedLabel.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds)
,这会告诉标签其首选的最大宽度,以便它可以计算多行文本所需的高度。通常你会在表格视图单元子类中这样做。
我已经在您的项目中对此进行了测试,并且可以正常工作
【讨论】:
我花了 3 天时间阅读这些文章 :) 如果你有时间,我建议你查看我的代码。 抱歉,我现在不能这样做,因为我正在参加培训课程。我以前做过这个,所以我有一个解决方案,一旦我回到笔记本电脑上,我就会进行编码。 :) 将estimatedRowHeight
设置为任何值修复了单元格高度在推送时被破坏的问题 - 仍然存在一个问题:推送时,tableview 的垂直位置被改变,并且选定的单元格跳出视图。【参考方案4】:
你必须设置estimatedRowHeight
:
// setup automatic row height
self.tableView.rowHeight = UITableViewAutomaticDimension
// whatever you think is the approximate row height
self.tableView.estimatedRowHeight = 44
【讨论】:
【参考方案5】:这里还遇到了一个替代方案http://useyourloaf.com/blog/2014/08/07/self-sizing-table-view-cells.html。评论提到 -
在从 cellForRowAtIndexPath 返回之前,只需将单元格布局设置为子视图:
[cell setNeedsDisplay];
[cell layoutIfNeeded];
【讨论】:
这不起作用。你可以用我的项目测试一下。 让我克隆你的项目并尝试 您可以将您的更改推送到 github 存储库吗?我添加了这两行,但它对我没有任何改变。 我的意思是真正的问题是当您单击一个单元格并返回时。你仍然得到正确的结果吗? 现在我意识到当你从细节视图控制器点击返回按钮时它会恢复。以上是关于UITableView 动态单元格高度在过渡或旋转时中断的主要内容,如果未能解决你的问题,请参考以下文章
UITableView 自定义单元格高度未正确管理 swift 中的动态约束
UITableView - 由单元格本身控制的动态单元格高度