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


79

可变长度的动态文本将注入到表格单元格标签中。为了动态调整tableview单元的高度,我在中实现了viewDidLoad()

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

这对于尚未UITableViewAutomaticDimention滚动到的单元格效果很好(滚动到该单元格时即会调用),但不适用于最初在向表中加载数据时在屏幕上呈现的单元格。

我尝试过简单地重新加载数据(如许多其他资源中所建议):

self.tableView.reloadData()

在这两个方面viewDidAppear()viewWillAppear()都没有用。我迷路了..有人知道如何让xcode渲染屏幕上最初加载的单元格的动态高度吗?

如果有更好的替代方法,请告诉我。


您对单元格设置的高度限制是否正确,我在使用Xcode 6.3版本时没有看到任何与此相关的问题。甚至可以在github上有一个示例项目。github.com/darren102/DTFAutomaticCellHeight
darren102

1
我通过过度补偿标签的潜在高度解决了这个问题。请在下面查看我的答案。无论如何,如果您有更好的解决方案,请告诉我!
simplexity 2015年

Answers:


114

试试这个:

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

编辑

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

斯威夫特4

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

斯威夫特4.2

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

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

PS:此功能需要顶部和底部约束。

这是例子


3
@bashan完美地工作。确保您已给出适当的约束。
iDhaval'2

2
不起作用 如果一个单词太长但不够长,似乎无法正确呈现,这似乎是一个错误。如果只是几句话,它似乎可以正常工作。
吉夫斯

6
直到我添加了底部约束,这对我才起作用。我认为在您的答案中值得注意的是,必须设置最高和最低约束才能使其正常工作。
米奇唐尼

2
要使其正常工作,必须有底部和顶部约束。
Antony Ouseph '18

2
要使其正常工作,必须对“单元元素”设置上
下限

37

用这个:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

并且不要使用:heightForRowAtIndexPath委托函数

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


4
底部约束很重要!我错过了,想知道为什么无法计算高度。
coyer

我落后于此heightForRowAtIndexPath
500服务器错误

@Javeed我想你可以使用它像静态细胞或动态小区的任何地方..
AMI室温

16

SWIFT 3

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160

和!!!在storyBoard中:您必须为Label设置顶部和底部约束。没有其他的。


11

通过Interface Builder参数解决了此奇怪的错误,因为其他答案无法解决该问题。

我所做的只是使默认标签尺寸大于可能的内容大小,并且也将其反映在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

这实际上允许代码将初始标签缩小到正确的大小。换句话说,它从来没有向外扩张到更大的尺寸,但总是可以缩小下来......此外,没有更多的self.tableView.reloadData()被需要viewWillAppear()

我知道这不能覆盖高度可变的内容大小,但是在我的内容具有最大可能字符数的情况下,这种方法有效。

不确定这是Swift还是Interface Builder中的错误,但它的工作原理像一个魅力。试试看!


我也有同样的问题。我已经更新了答案。它解决了我的问题。仅定义此方法并删除所有与高度有关的内容。
iDhaval 2015年

8

设置行高和估计行高的自动尺寸,并确保执行以下步骤:

@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(&换行模式=截尾)
  • 设置相对于其superview /单元容器的所有约束(上,下,左左)。
  • 可选的:如果您希望标签覆盖最小的垂直区域,即使没有数据,也设置标签的最小高度。

这是带有动态高度限制的样本标签。

在此处输入图片说明


1
Krunal提到的ViewDidLoad()中的条目是我的解决方案。
SHS

7

UITableView的动态大小调整单元格需要2件事

  1. 在表格视图单元格内为视图设置正确的约束(大多数情况下,包括为视图提供适当的顶部,底部和中性约束)
  2. 在viewDidLoad()中调用TableView的这些属性

     tableView.rowHeight = UITableViewAutomaticDimension
    
     tableView.estimatedRowHeight = 140
    

是用swift 3编写的有关自调整大小(动态表格视图单元格)的精彩教程。


6

对于Swift 3,您可以使用以下命令:

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

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

3

对于Swift 4.2

@IBOutlet weak var tableVw: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Set self as tableView delegate
    tableVw.delegate = self

    tableVw.rowHeight = UITableView.automaticDimension
    tableVw.estimatedRowHeight = UITableView.automaticDimension
}

// UITableViewDelegate Method 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return UITableView.automaticDimension
}

快乐编码:)


2

尝试

override func viewWillAppear(animated: Bool) {
    self.tableView.layoutSubviews()
}

我有同样的问题,对我有用。


我将尝试一下,让您知道会发生什么。谢谢你的建议!问了将近一年之后,除了我自己的答案,我没有找到其他答案!希望你的作品!
simplexity

确保在调用layoutsubviews之前先调用super.viewWillAppear(animated)
Alan Scarpa

2

为了使UITableViewCell的自动调整大小正常工作,请确保您正在执行以下更改:

  • 在Storyboard中,您的UITableView应该只包含动态原型单元格(不应使用静态单元格),否则自动调整大小将不起作用。
  • 在Storyboard中,您的UITableViewCell的UILabel已针对所有4个约束(顶部,底部,前导和尾随约束)进行了配置。
  • 在Storyboard中,您的UITableViewCell的UILabel的行数应为0
  • 在UITableView属性下面的UIViewController的viewDidLoad函数中设置:

    self.tableView.estimatedRowHeight = <minimum cell height> 
    self.tableView.rowHeight = UITableViewAutomaticDimension
    

如何使用静态单元实现相同?
贾维德(Javeed)

在尝试了这里提供的所有解决方案之后,只有这个(设置<minimum cell height>estimatedRowHeight)真正解决了我的问题。在此之前,单元进行了自动调整大小,但是我也收到了各种约束警告。现在我不知道了!所以,非常感谢您,安舒尔!
RoberRM

2

对于Swift,我也在iOS 9.0和iOS 11(Xcode 9.3)中选中了此答案

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

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

在这里,您需要添加顶部,底部,右侧和左侧约束


2

就我而言-在情节提要中,我有两个标签,如下图所示,在我将其相等之前两个标签都已设置了所需的宽度值。取消选择后,它将变为自动,并且像往常一样,下面的内容应该像魅力一样工作。

1.rowHeight = UITableView.automaticDimension, and
2.estimatedRowHeight = 100(In my case).
3.make sure label number of lines is zero.

在此处输入图片说明


2

这在做两件事时很简单:

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

因此,布局引擎可以计算像元高度并正确应用该值。


1

我只是从您的解决方案中得到启发,并尝试了另一种方法。

请尝试添加tableView.reloadData()viewDidAppear()

这对我有用。

我认为滚动背后的东西与reloadData“相同”。滚动屏幕时,就像调用reloadData()when一样viewDidAppear

如果这行得通,请回复这个答案,这样我就可以确定这个解决方案。


我将尝试一下并进行更新,以查看是否创建了相同的解决方案。谢谢!
simplexity

对不起,康,对布局没有任何影响。它将它们保留为在Interface Builder中设置的静态值,而不是将它们收缩包装为适当的大小。
simplexity

1

不幸的是,我不确定自己缺少什么。上面的方法对我来说无法获取xib单元格的高度,也无法让layoutifneeded()或UITableView.automaticDimension进行高度计算。我一直在搜索并尝试3到4个晚上,但找不到答案。不过,此处或其他帖子上的一些答案确实为我提供了解决方法的提示。这是一个愚蠢的方法,但它可以工作。只需将所有单元格添加到数组中即可。然后在xib故事板上设置每个高度限制的出口。最后,将它们加到heightForRowAt方法中。如果您不熟悉这些API,那将很简单。

斯威夫特4.2

CustomCell.Swift

@IBOutlet weak var textViewOneHeight: NSLayoutConstraint!
@IBOutlet weak var textViewTwoHeight: NSLayoutConstraint!
@IBOutlet weak var textViewThreeHeight: NSLayoutConstraint!

@IBOutlet weak var textViewFourHeight: NSLayoutConstraint!
@IBOutlet weak var textViewFiveHeight: NSLayoutConstraint!

MyTableViewVC.Swift

.
.
var myCustomCells:[CustomCell] = []
.
.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = Bundle.main.loadNibNamed("CustomCell", owner: self, options: nil)?.first as! CustomCell

.
.
myCustomCells.append(cell)
return cell

}


override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

   let totalHeight = myCustomCells[indexPath.row].textViewOneHeight.constant + myCustomCells[indexPath.row].textViewTwoHeight.constant +  myCustomCells[indexPath.row].textViewThreeHeight.constant + myCustomCells[indexPath.row].textViewFourHeight.constant + myCustomCells[indexPath.row].textViewFiveHeight.constant

  return totalHeight + 40 //some magic number


}

1

我用这些

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

    return 100
}

1

除了别人说的话

设置相对于概述的标签约束!

因此,与其将标签的约束相对于周围的其他事物放置,不如将其约束到表视图单元格的内容视图。

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

然后在ViewDidLoad添加:

tableView.estimatedRowHeight = 695

tableView.rowHeight = UITableViewAutomaticDimension

0

您应该只为单元格视图上的每个对象设置TOPBOTTOMHEIGHT的所有约束,如果有,则删除存在的中间Y位置。因为您没有这样做,所以将工件放在另一个视图上。


3
您好!,这个答案可能不错,但是最好提供一个可以说明并演示您答案的工作示例。
ItamarG3

0

对于目标c,这是我不错的解决方案之一。对我有用。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.textLabel.text = [_nameArray objectAtIndex:indexPath.row];
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

我们需要应用这两个更改。

1)cell.textLabel.numberOfLines = 0;
  cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;

2)return UITableViewAutomaticDimension;

0

最初我也遇到了这个问题,我已经从此代码解决了我的问题,请尝试避免使用self.tableView.reloadData()代替此代码来实现动态高度

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];

0

当使用静态时UITableView,我在UILabels中设置所有值,然后调用tableView.reloadData()


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

并且不要忘记为标签添加botton约束


0

雨燕5享受

tablev.rowHeight = 100
tablev.estimatedRowHeight = UITableView.automaticDimension


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tablev.dequeueReusableCell(withIdentifier: "ConferenceRoomsCell") as! ConferenceRoomsCell
    cell.lblRoomName.numberOfLines = 0
    cell.lblRoomName.lineBreakMode = .byWordWrapping
    cell.lblRoomName.text = arrNameOfRooms[indexPath.row]
    cell.lblRoomName.sizeToFit()
    return cell
}

-1
self.Itemtableview.estimatedRowHeight = 0;
self.Itemtableview.estimatedSectionHeaderHeight = 0;
self.Itemtableview.estimatedSectionFooterHeight = 0;


[ self.Itemtableview reloadData];
self.Itemtableview.frame = CGRectMake( self.Itemtableview.frame.origin.x,  self.Itemtableview.frame.origin.y,  self.Itemtableview.frame.size.width,self.Itemtableview.contentSize.height + self.Itemtableview.contentInset.bottom + self.Itemtableview.contentInset.top);

尽管这段代码可以解决问题,但包括解释如何以及为什么解决该问题的说明,确实可以帮助提高您的帖子质量,并可能导致更多的投票。请记住,您将来会为读者回答问题,而不仅仅是现在问的人。请编辑您的答案以添加说明,并指出适用的限制和假设。
Suraj Rao

-3

设置适当的约束并将委托方法更新为:

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

这将解决动态像元高度问题。如果不是,则需要检查约束。


1
与同一页上的艾哈迈德·洛特菲Ahmed Lotfy)的答案相同的代码...
埃里克·阿亚

嗯,我已经检查过快速3. *,我错过了艾哈迈德·
安斯

1
您还必须提供估算的行高才能使代码正常工作
Mohsen Shakiba
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.