在 iOS 7 中根据单元格的文本计算单元格高度

Posted

技术标签:

【中文标题】在 iOS 7 中根据单元格的文本计算单元格高度【英文标题】:Calculate cell height based on cell's text in iOS 7 【发布时间】:2013-11-25 20:59:31 【问题描述】:

有许多使用“sizeWithFont”或类似内容的解决方案,而这恰好在 ios 7 中已被弃用。

这是迄今为止我拼凑的一些代码。高度发生变化,但完全不准确:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

// Configure the cell...
cell.textLabel.text = "The Cell's Text!";
cell.textLabel.numberOfLines = 0;
[cell.textLabel setLineBreakMode:NSLineBreakByWordWrapping];
[cell.textLabel sizeToFit];

return cell;


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

CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBounds.size;

NSAttributedString *aString = [[NSAttributedString alloc] initWithString:"The Cell's Text!"];
UITextView *calculationView = [[UITextView alloc] init];
[calculationView setAttributedText:aString];
CGSize size = [calculationView sizeThatFits:CGSizeMake(screenSize.width, FLT_MAX)];
return size.height;

再举一个例子,这是一个类似的答案:https://***.com/a/9828777/693121 虽然正如我之前所说,这使用了已弃用的代码。

【问题讨论】:

【参考方案1】:

您应该使用文档中提到的方法来替换旧的方法——boundingRectWithSize:options:attributes:context:。这是我认为应该可行的示例(无论如何它都适用于多行标签)。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    NSStringDrawingContext *ctx = [NSStringDrawingContext new];
    NSAttributedString *aString = [[NSAttributedString alloc] initWithString:@"The Cell's Text!"];
    UITextView *calculationView = [[UITextView alloc] init];
    [calculationView setAttributedText:aString];
    CGRect textRect = [calculationView.text boundingRectWithSize:self.view.frame.size options:NSStringDrawingUsesLineFragmentOrigin attributes:@NSFontAttributeName:calculationView.font context:ctx];
        return textRect.size.height;
  

这假设您希望文本视图的大小与 self.view 相同。如果没有,您应该为您的文本视图使用 initWithFrame,并为 boundingRectWithSize: 参数传递calculationView.frame.size。

【讨论】:

出于某种原因,它总是返回 13.8 的高度?不管“aString”变量中有多少文本。 @Demasterpl,对不起,我在答案中使用了错误的选项参数,它应该是 NSStringDrawingUsesLineFragmentOrigin。我已经更正了我的答案。 这似乎返回了一个可观的值,尽管有时即使高度很大,但它似乎仍然保持默认高度。此外,如果我删除了单元格属性(如 sizeToFit 和 setLineBreakMode),它似乎并没有什么不同。 :( @Demasterpl,什么保持默认高度?单元格,还是文本视图? 我有 NSStringDrawingUsesLineFragmentOrigin 在那里,我仍然得到 @Demasterpl 得到的 13.8。【参考方案2】:

这是最简单的版本,iOS 7 完成了所有繁重的工作(仅适用于基于自动布局的 uitableviewcells):

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

   CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"Cell"];

   [self configureCell:cell];

   // edit: Need to call [cell layoutIfNeeded]; otherwise the layout changes wont be applied to the   cell

   [cell layoutIfNeeded];


   return [cell.contentView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize].height;

systemLayoutSizeFittingSize 重新评估自动布局约束并返回单元格的完美高度。简单吧?

【讨论】:

方法是什么[self configureCell:cell]; ? 依赖于数据对象的单元格的基本设置(例如,设置标签)。有了它,我用内容“填充”单元格,因此自动布局可以自动确定所需的高度【参考方案3】:

我从我的同事 (ANIRUDH) 那里得到它并且工作正常,可能会有所帮助:

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


//Calculating height on base of length of text
    UIFont *font =  [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    NSAttributedString *attributedText =
    [[NSAttributedString alloc]
     initWithString:YOURSTRING //[NSString string withformat:@"\n Yourstring"] \n for: number of lines require for static label in cell
     attributes:@
     
     NSFontAttributeName: font
     ];
    CGRect rect = [attributedText boundingRectWithSize:(CGSize)CELL_CONTENT_WIDTH, CGFLOAT_MAX
                                               options:NSStringDrawingUsesLineFragmentOrigin
                                               context:nil];
    CGSize size = rect.size;

    //  NSString *height = [NSString stringWithFormat: @"%.2f", ceilf(size.height)+22];
    return (ceilf(size.height)+22)*0.6; //change 0.6 to 0.9 according to the difference in required and extra calculted height, it works for me every time

【讨论】:

【参考方案4】:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    NSString *yourText = [[resultArray objectAtIndex:indexPath.row] valueForKey:@"review_text"];
    CGSize lblwidth = CGSizeMake(300, CGFLOAT_MAX);
    CGSize requiredSize = [yourText sizeWithFont:[UIFont fontWithName:@"CALIBRI" size:17] constrainedToSize:lblwidth lineBreakMode:NSLineBreakByWordWrapping];
    int calculatedHeight = requiredSize.height+50;
    return (float)calculatedHeight;

【讨论】:

【参考方案5】:

要获取字符串的大小,您应该使用- (CGSize)sizeWithAttributes:(NSDictionary *)attars

因此,对于您的示例,您可以这样计算文本标签的高度:

CGSize *cellSize = [cell.textLabel.text sizeWithAttributes:@NSFontAttributeName:[cell.textLabel.font]];

CGSize *rowSize = [aString sizeWithAttributes:nil];

【讨论】:

这行不通。来自 Apple 的文档:“如果要在单行上使用指定的字体呈现,则返回字符串的大小。”如果您尝试根据多行标签更改单元格高度,这将没有用。

以上是关于在 iOS 7 中根据单元格的文本计算单元格高度的主要内容,如果未能解决你的问题,请参考以下文章

如何在swift ios中调整集合视图单元格的高度?

在tableview ios中使用UILabel的单元格的动态高度

iOS8“现在”改变动态单元格的高度,重新内部单元格内容

根据 UILabel 文本的数量增加 tableview 单元格的高度

计算 NSString 高度以在 collectionView 单元格中使用

在自定义单元格中调整 iOS 7.1 中的 UILabel 大小