UITableView单元格的动态高度问题(Swift)

94

可变长度的文本数据被注入到tableview cell标签中。为了使每个单元格的高度正确调整,我在viewDidLoad()中实现了以下代码:

self.tableView.estimatedRowHeight = 88.0
self.tableView.rowHeight = UITableViewAutomaticDimension

这估计高度为88.0像素,并且如果更大则应自动调整高度。它对于尚未滚动到的单元格(因为在滚动到单元格时调用了UITableViewAutomaticDimension)效果完美,但不适用于最初在加载数据的同时呈现在屏幕上的单元格。

我已经尝试重新加载数据(如许多其他资源建议的那样):

self.tableView.reloadData()

viewDidAppear()viewWillAppear()中都试过了,但没有帮助。我很迷茫...有谁知道如何为最初加载到屏幕上的单元格呈现动态高度吗?


你的单元格高度限制设置正确吗?我在使用Xcode 6.3版本时没有遇到任何问题。甚至在Github上有一个示例项目可以正常工作。https://github.com/darren102/DTFAutomaticCellHeight - darren102
1
我通过过度补偿标签的潜在高度来解决了这个问题。请参见下面的答案。无论如何,如果您有更好的解决方案,请告诉我! - simplexity
26个回答

133

试试这个:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

编辑

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Swift 4

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Swift 4.2

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

定义以上两种方法。
它解决了这个问题。

PS:为使其正常运行,需要设置顶部和底部约束。

这里是示例


4
它运行得非常完美。确保您已经给出了适当的限制条件。 - iDhaval
3
无法运行。如果一个单词太长但不够长,似乎会出现错误,无法正确渲染。如果是几个单词,则似乎能正常工作。 - Jeeves
9
在我添加了底部约束之前,这种方法对我没有用。我认为在您的回答中值得注意的是,必须设置顶部和底部约束才能使其生效。 - Mitch Downey
3
需要底部和顶部的约束条件才能使其工作。 - Antony Ouseph
3
为了使这个功能正常工作,需要为“单元元素”设置底部和顶部约束。 - EnasAZ
显示剩余5条评论

48

使用这个:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

不要使用:heightForRowAtIndexPath委托功能。

另外,在故事板中不要设置包含大量数据的标签的高度。给它 top, bottom, leading, trailing 约束。


5
底部限制很重要!我忘了这个,所以不知道为什么高度无法计算。 - coyer
我正在离开这个heightForRowAtIndexPath - 500 Server error
@Javeed 我认为你可以在任何地方使用它,如静态单元格或动态单元格。 - ami rt
我不知道为什么这个方法起作用,而不是委托函数。不过还是谢谢。 - Amit Khetan

19

Swift 3

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160

在StoryBoard中,你必须为标签设置顶部和底部约束。其他的都不用设置。


16

通过 Interface Builder 参数解决了这个奇怪的 bug,因为其他答案没有解决问题。

我所做的只是将默认标签大小调整为可能的内容大小更大,并在 estimatedRowHeight 高度中反映出来。以前,我在 Interface Builder 中将默认行高设置为 88px,并在我的控制器 viewDidLoad() 中进行了反映:

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0

但那样做没有效果。所以我意识到内容永远不会变得比100px更大,因此我将默认单元格高度设置为108px(大于潜在内容),并在控制器的viewDidLoad()中反映出来:

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 108.0

实际上,这允许代码将初始标签缩小到正确的大小。换句话说,它从未扩展到更大的尺寸,但始终可以缩小... 另外,在viewWillAppear()中不需要额外的self.tableView.reloadData()

我知道这并不能涵盖高度可变的内容大小,但在我所处的情况下,这很有效,因为内容具有最大可能的字符计数。

不确定这是Swift或Interface Builder中的错误,但它运行得很好。试一试吧!


我也有同样的问题。我已经更新了我的答案,它解决了我的问题。只需定义此方法并删除所有与高度相关的内容即可。 - iDhaval

13

设置行高的自动尺寸和预估行高,并确保按照以下步骤进行:

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension

}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension
}

例如:如果您在UITableviewCell中有一个标签,则:

  • 将行数设置为0(并将换行模式设置为截断尾部)
  • 相对于其父视图/单元格容器设置所有约束(顶部、底部、右侧和左侧)。
  • 可选项:如果要覆盖最小垂直区域,即使没有数据也要设置标签的最小高度。

这是带动态高度约束的示例标签:

enter image description here


1
Krunal提出的ViewDidLoad()中的条目对我来说是一个解决方案。 - SHS

9

对于 Swift 3,您可以使用以下代码:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

"UITableViewAutomaticDimension"已被弃用,在Swift 5中,它是"UITableView.automaticDimension"。 - Naval Hasan

8

UITableView的动态大小调整需要满足以下2个条件:

  1. Setting the the right constraint of your view inside the table view cell (mostly it includes giving your view proper top , bottom and traling constraints)
  2. Calling these properties of TableView in viewDidLoad()

     tableView.rowHeight = UITableViewAutomaticDimension
    
     tableView.estimatedRowHeight = 140
    
这是一篇关于自适应(动态表格视图单元)的精彩教程,用Swift 3编写。

此链接


5
在我的情况下 - 在storyboard中,我有两个标签,如下图所示, 这两个标签在我将它们设置为相等之前,都已经设置了期望的宽度值。一旦你取消选择,它就会变成自动,并且通常情况下,以下内容应该像魅力一样工作。
1.rowHeight = UITableView.automaticDimension, and
2.estimatedRowHeight = 100(In my case).
3.make sure label number of lines is zero.

enter image description here


5

除了其他人说的内容外,

将标签的约束设置为相对于超级视图!

因此,不要将您的标签的约束放置在其周围的其他物体上,而是将其限制为表格视图单元格的内容视图。

然后,请确保将标签的高度设置为大于或等于0,并且行数设置为0。

然后,在ViewDidLoad中添加:

tableView.estimatedRowHeight = 695

tableView.rowHeight = UITableViewAutomaticDimension

将您的标签约束相对于超级视图设置!:节省了我的时间!!谢谢。 - ACAkgul

4

做这两件事情时非常简单:

  1. 设置自动高度
tableView.rowHeight = UITableView.automaticDimension
  1. 从上到下,使用FULL约束创建所有的TableViewCells。最后一个元素MUST定义一些底部间距以结束该单元格。

这样布局引擎可以计算出单元格的高度并正确应用该值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接