带有 UILabel 和随机文本长度的 UITableViewCell 高度问题

Posted

技术标签:

【中文标题】带有 UILabel 和随机文本长度的 UITableViewCell 高度问题【英文标题】:Problems with UITableViewCell heights with a UILabel and random text lengths 【发布时间】:2011-08-22 21:45:19 【问题描述】:

我目前正在尝试让 UITableView 使用基于数组中文本的自定义单元格高度。我看到的问题是文本似乎在一点上挤压在一起,而不是填充自定义单元格的整个长度。这会导致文本在单元格上重叠,有时会在单元格下方消失。

这是我用于确定单元格高度的代码,我不确定标准的 UILabel 文本高度,但这似乎在字体高度 I 上运行良好。

if (indexPath.section == 0) 

    NSString *text = [[self.recipeDict objectForKey:@"Ingredients"] objectAtIndex:[indexPath row]];

    CGSize constraint = CGSizeMake(320 - (10 * 2), 20000.0f);

    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

    CGFloat height = size.height;

    return height + 20;

另外,如果创建单元格会阻碍我的问题,或者只是帮助您了解正在发生的事情,这也是。

UITableViewCell *cell;
UITableViewCell *ingredientCell;
UITableViewCell *methodCell;

if (indexPath.section == 0) 
    UILabel *ingredientText;

    static NSString *ingredientCellIdentifier = @"Ingredient Cell";

    ingredientCell = [tableView dequeueReusableCellWithIdentifier: ingredientCellIdentifier];

    if (ingredientCell == nil)
    
        ingredientCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: ingredientCellIdentifier] autorelease];

        ingredientText = [[UILabel alloc] initWithFrame:CGRectMake(15, 7, 290, 44)];
        [ingredientText setLineBreakMode:UILineBreakModeWordWrap];
        [ingredientText setNumberOfLines:0];
        [ingredientCell.contentView addSubview:ingredientText];

        ingredientText.tag = 1;

        [ingredientText release];

        ingredientCell.contentMode = UIViewContentModeRedraw;
    

    ingredientText = (UILabel*)[ingredientCell viewWithTag:1];
    ingredientText.text = [[self.recipeDict objectForKey:@"Ingredients"] objectAtIndex: indexPath.row];
    [ingredientText sizeToFit];

    return ingredientCell;

这是我第二次尝试解决这个问题,但它似乎超出了我目前的能力,所以我欢迎通过经验获得智慧。

更新 -

经过进一步调查,调整大小的 UILabel 成分文本似乎是导致问题的原因。

它开始时与显示的文本一样高,但是当该标签以更大的高度重新绘制用于需要更多行的另一段文本时,它永远不会再次缩小。看来sizeToFit方法是优先使用可用高度,而不是占用宽度缩小高度。

现在我在 sizeToFit 之后再次设置了宽度,这解决了这个问题,但它会根据标签的高度导致奇怪的间距。

【问题讨论】:

【参考方案1】:

有几点:

您尚未为 UILabel 设置字体,这意味着您正在调整大小为未知高度 您需要设置 UILabel 自动调整大小掩码,以便在单元格高度发生变化时调整大小

这是工作代码(已测试):

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    if (indexPath.section == 0) 

        NSString *text = [_items objectAtIndex:[indexPath row]];

        CGSize constraint = CGSizeMake(320 - (10 * 2), 20000.0f);

        CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

        CGFloat height = size.height;

        return height + 20;
    

    return tableView.rowHeight;


#pragma mark - UITableViewDatasource

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    UITableViewCell *cell;
    UITableViewCell *ingredientCell = nil;
    UITableViewCell *methodCell;

    if (indexPath.section == 0) 
        UILabel *ingredientText;

        static NSString *ingredientCellIdentifier = @"Ingredient Cell";

        ingredientCell = [tableView dequeueReusableCellWithIdentifier: ingredientCellIdentifier];

        if (ingredientCell == nil)
        
            ingredientCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: ingredientCellIdentifier] autorelease];

            ingredientText = [[UILabel alloc] initWithFrame:ingredientCell.bounds];
            ingredientText.font = [UIFont systemFontOfSize:12.0f];
            ingredientText.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
            [ingredientText setLineBreakMode:UILineBreakModeWordWrap];
            [ingredientText setNumberOfLines:0];
            [ingredientCell.contentView addSubview:ingredientText];

            ingredientText.tag = 1;

            [ingredientText release];

            ingredientCell.contentMode = UIViewContentModeRedraw;
        

        ingredientText = (UILabel*)[ingredientCell viewWithTag:1];
        ingredientText.text = [_items objectAtIndex: indexPath.row];

        return ingredientCell; 
    


确保您始终返回 tableView:cellForRowAtIndexPath: 和 tableView:heightForRowAtIndexPath: 方法的值

【讨论】:

我注意到您在 cellForRowAtIndexPath: 方法的开始处将 IngredientCell 设置为 nil。似乎每次使用时都会强制重新加载整个单元格。这是不是调整现有单元格大小的最佳方法? 我尝试了这段代码,但在快速重绘单元格时仍然无法正确绘制单元格。当我快速上下滑动 UITableView 时,我看到了这个问题。当它们重绘时,它们看起来比应有的窄,大约是宽度的一半。 我确实将return ingredientCell 移到了if 块之外;所以它应该总是初始化为nil以避免垃圾被返回。我将它移回了它,以尽可能接近您的原始代码。 您的代码中还有其他内容吗?运行我的小示例应用程序时没有发现任何问题。 感谢您关注我。缩小 UILabel 的宽度似乎更像是一个问题,因为另一段加载的文本的高度已经增加。例如,文本的第一位将标签设置为 44 的高度,UILabel 会按预期填充。然后我在文本项列表中快速上下滚动,这些项占用更多的文本行,因此使标签高度更大,例如 180。 sizeToFit 似乎优先适应现有标签的高度而不是宽度。这使标签更高而不是填充宽度【参考方案2】:

这个问题的解决方法是在单元格高度方法中的常量中指定的宽度与稍后在 cellForRowAtIndexPath 方法中指定的单元格文本的框架不匹配。

一旦这些相同,问题就会自行解决。

不同的常量大小导致报告的 UILabel 高度不一致且不准确。这导致设置了不正确的表格行高。

【讨论】:

以上是关于带有 UILabel 和随机文本长度的 UITableViewCell 高度问题的主要内容,如果未能解决你的问题,请参考以下文章

使用界面生成器和 XIB,带有不同颜色文本的 UIlabel

如何比较 Swift 中的字符?我有带有文本和 UITextField 的 UILabel

Swift - UILabel 自动调整为文本长度

如何根据文本长度计算 UILabel 宽度?

当 UILabel 文本长度较大时,UILabel 或 UIButton 类似于“查看更多”

如何使用自动布局在 iOS 中根据文本长度更改 UILabel 宽度