ios 如何根据文本标签长度动态设置表格单元格高度?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16344400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:25:53  来源:igfitidea点击:

how to set table cell height dynamically depending on text label length?

iosobjective-cuitableview

提问by Prefix

I am trying to learn Obj-C and iOS programming, but am still very new. I decided to try and make a simple Reddit client application. I am trying to display the front page posts within a UITableView, with each post represented by its own cell.

我正在尝试学习 Obj-C 和 iOS 编程,但我仍然很陌生。我决定尝试制作一个简单的 Reddit 客户端应用程序。我正在尝试在 中显示首页帖子UITableView,每个帖子由其自己的单元格表示。

On the cell, here is how I am setting the title:

在单元格上,这是我设置标题的方式:

cell.textLabel.numberOfLines = 0;
cell.textLabel.text = [[tempDictionary objectForKey:@"data"] objectForKey:@"title"];   
[cell.textLabel sizeToFit];

However, the cell ends up clipping itself if the title text is too long. Here's a picture:

但是,如果标题文本太长,单元格最终会自行剪裁。这是一张图片:

enter image description here

在此处输入图片说明

How can I make my cells automatically adjust their heights to accommodate longer title labels, without intersecting other cells or the detail text label?

如何让我的单元格自动调整它们的高度以适应更长的标题标签,而不与其他单元格或细节文本标签相交?

Thank you for any help!

感谢您的任何帮助!

回答by Dima Deplov

For new iOS 8 there is a new way to make this simple.

对于新的 iOS 8,有一种新方法可以让这一切变得简单。

There is new a parameter that calculates your cell height with respect of your auto layout constraints. This is UITableViewAutomaticDimension. You can use it in the viewWillAppearmethod of your view controller.

有一个新参数可以根据自动布局约束计算单元格高度。这是UITableViewAutomaticDimension。您可以在viewWillAppear视图控制器的方法中使用它。

Objective C:

目标 C:

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  self.tableView.estimatedRowHeight = 70.0; // for example. Set your average height 
  self.tableView.rowHeight = UITableViewAutomaticDimension;
  [self.tableView reloadData];
}

Swift:

迅速:

override func viewWillAppear(animated: Bool) {
    self.tableView.estimatedRowHeight = 70 // for example. Set your average height 
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.reloadData()

} 

Work nice and as you want at your example. As for me, I add height things in viewDidLoadand left in viewWillAppearonly reloadData(). There is also useful source.

在你的例子中工作得很好,就像你想要的那样。至于我,我只viewDidLoadviewWillAppearreloadData() 中添加和留下高度的东西。还有有用的来源

From documentation: The default value of rowHeight is UITableViewAutomaticDimension.I leave the code as it is, for now, but keep in mind that you don't need to set row height in iOS 8+.

来自文档:The default value of rowHeight is UITableViewAutomaticDimension.我暂时保留代码,但请记住,您不需要在 iOS 8+ 中设置行高。

The main thing you need to do is to set all constraints explicitly e.g. to the leading, trailing, top and bottom. Try it first, without adding any lines of code above.

您需要做的主要事情是明确设置所有约束,例如前导、尾随、顶部和底部。先尝试一下,不要在上面添加任何代码行。

回答by PHD

You should check out the documentation referencefor

你应该看看文档参考

-[UITableViewDelegate tableView:heightForRowAtIndexPath:]

Essentially, you will need to measure the text yourself in order to return the correct dimensions for each table row. If they're simple NSStrings, which they appear to be from your screenshot, you can use the NSString UIKit Additionsto measure them, e.g.

本质上,您需要自己测量文本,以便为每个表格行返回正确的尺寸。如果它们很简单NSStrings,从您的屏幕截图中可以看出,您可以使用NSString UIKit Additions来测量它们,例如

-[NSString sizeWithFont:constrainedToSize:]

Where the constrained size could have infinite height but the width of your table cell's content view.

受约束的大小可能具有无限的高度,但表格单元格的内容视图的宽度。

If they are attributed strings, there is a similar method in the NSAttributedString UIKit additions called boundingRectWithSize:options:context:

如果它们是属性字符串,则在 NSAttributedString UIKit 中添加了一个类似的方法,称为 boundingRectWithSize:options:context:

回答by matt

It happens that my app TidBITS News does exactlywhat you're describing. And I believe it was one of the first apps to figure out howto do it; at least, at the time I wrote it, I knew of no other apps that did this. I published my method in my Programming iOS 4book, and since then it has become commonplace (though I'm not saying everyone got it from me; there is basically only one sensible way to approach it).

碰巧我的应用程序 TidBITS News完全符合您的描述。我相信它是最早弄清楚如何做到这一点的应用程序之一;至少,在我写它的时候,我知道没有其他应用程序可以做到这一点。我在我的编程 iOS 4书中发表了我的方法,从那时起它变得司空见惯(虽然我并不是说每个人都从我这里得到它;基本上只有一种明智的方法来处理它)。

Here's the explanation from the current version of my book:

这是我书的当前版本的解释:

http://www.apeth.com/iOSBook/ch21.html#_variable_row_heights

http://www.apeth.com/iOSBook/ch21.html#_variable_row_heights

As you can see, the trick is to work out the heights of all the rows in advanceby calling sizeWithFont:constrainedToSize:on the label with the data it will contain in each row, and doing the necessary math. This is because tableView:heightForRowAtIndexPath:is going to be called up front, over and over, to determine the heights of everyrow, beforeyou are asked for the data.

如您所见,诀窍是通过调用带有将包含在每行中的数据的标签并进行必要的数学运算来提前计算出所有行的高度。这是因为您被要求提供数据之前,将被反复调用以确定每一行的高度。sizeWithFont:constrainedToSize:tableView:heightForRowAtIndexPath:

Then, when you are asked for cellForRowAtIndexPath:, you use the results you derived in advance in order to lay out the cell within the height you previously calculated.

然后,当您被要求提供 时cellForRowAtIndexPath:,您可以使用您预先得出的结果,以便在您之前计算的高度内布置单元格。

On GithubI've also got a downloadable complete project example that you can read and run; it shows you how to do it with constraints (iOS 6 and later only). Look for the ch21example with variableHeightsin its name.

Github 上,我还有一个可下载的完整项目示例,您可以阅读和运行;它向您展示了如何使用约束(仅限 iOS 6 及更高版本)执行此操作。查找名称中ch21带有的示例variableHeights

回答by iOSGuru248

In your tableview heightForRowAtIndexPath delegate method:

在您的 tableview heightForRowAtIndexPath 委托方法中:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath   *)indexPath
{

if (indexPath.row == 2) {
  Message *aMessage = [customTableViewArray objectAtIndex:indexPath.row];

  if ( [aMessage.msgBody length] <= 0 )
    aMessage.msgBody = @"     ";
    CGSize constraint = CGSizeMake(450, 40000.0f);
    CGSize size = [aMessage.msgBody sizeWithFont:[UIFont fontWithName:@"Helvetica" size:14] constrainedToSize:constraint lineBreakMode:UILineBreakModeCharacterWrap];
    size.height = MAX(size.height,36);

    return 136+size.height;

} else if(indexPath.row > 1) {

      Message *aMessage = [customTableViewArray objectAtIndex:indexPath.row];

      if ( [aMessage.msgBody length] <= 0 )
        aMessage.msgBody = @"     ";
        CGSize constraint = CGSizeMake(450, 40000.0f);
        CGSize size = [aMessage.msgBody sizeWithFont:[UIFont fontWithName:@"Helvetica" size:14] constrainedToSize:constraint lineBreakMode:UILineBreakModeCharacterWrap];
        size.height = MAX(size.height,36);

        return 100+size.height;

} else {
      return 146;
   }

}

I apologize, I had only included part of the code. This is the whole thing. So basically if the message is empty it makes it one size. Then in the else if part of the statement, it gets the size of the message and bases the cell size on that message size.

抱歉,我只包含了部分代码。这就是整件事。所以基本上如果消息是空的,它就会使它成为一种大小。然后在语句的 else if 部分,它获取消息的大小并根据该消息大小确定单元格大小。