1

当表格单元格有很多文本和图像时,我在确定表格单元格的高度时遇到了问题。但问题是上下文相关的,取决于所使用的文本类型。我将解释这个问题,然后给出我用来格式化单元格和确定单元格高度的代码。当我在单元格左侧有一个图像时,我从图像的最大高度与文本的最大高度中获取单元格高度。问题是在所有情况下都没有正确计算文本高度。下面,我在底部单元格中有以下文本:

“P 154 越南家常菜:非常好!!将香料搅拌成糊状——效果很好;用西葫芦上剩下的酱汁烤;运作良好;厚猪排;在 450 和 525 之间煮 35 分钟”。

表格视图一直滚动到底部。如您所见,文本的底部不存在(“在 450 和 525 之间煮 35 分钟”)。实际发生的情况是没有正确确定文本宽度。下面,文本宽度被计算为 cell.textLabel.bounds.size.width: 234 像素。基于此,错误地计算了文本的高度。 模拟器屏幕抓取显示不完整的文本

但是,如果我按下辅助按钮 (“>”) 并进入下一个视图,然后从该视图返回(使用带有导航控制器的“后退”按钮),我通常会得到以下更改的表格显示(但有时我仍然得到上面的视图,没有剩余的文字): 显示完整文本的模拟器屏幕抓取

在这种情况下,表格视图第二次显示时,文本的宽度计算为 cell.textLabel.bounds.size.width: 163 像素。两个文本宽度之间的差异(234 - 163 = 71 像素)。图像宽度为 100 像素。不幸的是,情况比这更复杂:
1)如果单元格中没有图像,我确定文本的宽度没有问题。
2)如果我只使用一系列简单的文本行,例如一系列连续的数字/字母,每个字符后都有一个回车符,那么宽度是正确确定的。例如,如果单元格中的文本是:
1
2
3
4
5
6
7
8
9
0
A
B
C

3)如果单元格后面(下面)有大量整行文本(不是由回车后跟字符组成的文本)的单元格,那么我永远不会正确计算单元格宽度(因此高度永远不会计算正确)。

我尝试了什么?

在 cellForRowAtIndexPath 中,我尝试过: cell.textLabel.autoresizingMask = UIViewAutoresizingNone; 正如所有方向中 UITableViewCell 中的 Dynamic UILabel Heights/Widths所建议的那样,但这并没有改变这种情况。

我还尝试从计算 UILabel/UITableViewCell 的多行文本高度:计算与实际绘制到 cellForRowAtIndexPath 时的不同结果中的建议,这会强制文本标签的新宽度,但这不起作用。

一个有效的黑客

起作用的是强制文本标签宽度为 heightForRowAtIndexPath 内的正确宽度。但是,这肯定是一个hack。我想要一个更好的解决方案。想法?

代码

在 BUG74 之后的代码中是我在这里描述的问题。

// https://stackoverflow.com/questions/129502/how-do-i-wrap-text-in-a-uitableviewcell-without-a-custom-cell
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CustomCellCommentList";
    CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        NSLog(@"CommentList.cellForRowAtIndexPath: nil case");
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

        IF_IOS6_OR_GREATER(
            cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
        );
        IF_LESS_THAN_IOS6(
            cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        );

        // To remove any maximum limit, and use as many lines as needed, set the value of this property to 0.
        cell.textLabel.numberOfLines = 0;
        cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
        cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;

        cell.textLabel.autoresizingMask = UIViewAutoresizingNone;
    }

    NSDictionary *menuItemCommentDictionary =
    [Globals GetIthMenuItemComment: indexPath.row forMenuItem: menuItemName andRestaurant: restaurantName];

    //NSDate *commentDate = [menuItemCommentDictionary objectForKey:@"date"];

    if (CommentListDebug) NSLog(@"cellForRowAtIndexPath");

    UIImage *theIcon;
    NSString *imageFileName = [menuItemCommentDictionary objectForKey:COMMENT_KEY_IMAGE_FILENAME];

    if (imageFileName) {
        // Scaling images in table view cells
        // https://stackoverflow.com/questions/9046573/uitableviewcell-resize-image

#define DEFAULT_TABLE_CELL_HEIGHT 44
#define IMAGE_WIDTH_IN_TABLE_CELL 100
        /* I'm going to give images a constant width and adjust
         the height of the table cell according to their height.
         */
        theIcon = [PersistentStorage retrieveIconFromFile:imageFileName];

        if (CommentListDebug) NSLog(@"icon: %@", theIcon);

        //NSNumber *iconHeight  = [menuItemCommentDictionary objectForKey:@"imageIconHeight"];

        //if (CommentListDebug) NSLog(@"iconHeight: %d", [iconHeight intValue]);

        cell.imageView.image = theIcon;
    } else {
        if (CommentListDebug) NSLog(@"No image file name");
        cell.imageView.image = nil; // Otherwise, if using old cell, uses old icon image
    }

    NSString *cellText = [menuItemCommentDictionary objectForKey:@"menuItemComment"];

    // 1/5/13; Bug# 62; only if there is no icon/image and no text
    // should we mark as empty.
    if ((! imageFileName) && ((nil == cellText) || ([cellText length] == 0))) {
        cellText = EMPTY_TEXT; // temporary empty text
    }

    cell.textLabel.text = cellText;

    // BUG74: 1/29/13;
    // We are not having problems with the text width when there
    // is no icon, so only do this when there is an icon
    // NOTE: This does *not* work; for some reason, the frame.size.width
    // is not retained in the call to heightForRowAtIndexPath.
    if (imageFileName) {
        CGRect labelFrame = cell.textLabel.frame;
        labelFrame.size.width = 287 - 27 - theIcon.size.width;
        NSLog(@"CommentList.cellForRowAtIndexPath: labelFrame.size.width: %d", (int) labelFrame.size.width);
        cell.textLabel.frame = labelFrame;
        [cell.textLabel sizeToFit];
    }

    return cell;
}

- (CGFloat)tableView:(UITableView *)thisTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *menuItemCommentDictionary =
        [Globals GetIthMenuItemComment: indexPath.row forMenuItem: menuItemName andRestaurant: restaurantName];
    NSString *cellText  = [menuItemCommentDictionary objectForKey:@"menuItemComment"];

    // 1/5/13; Bug# 62; I'm going to allow empty comments in the case
    // where there is no picture and no text. This is to allow a user
    // to have a smiley rating only but no picture and no text.
    // The issue here is that with no text, the height of the row
    // is too small, and looks odd. And it's hard to select that row to
    // delete because it's not very tall.
    // My fix for this it to add some temporary empty text. I've used
    // non-white space text, because I still get the issue if I use
    // white space. If I add the display of smiley's in the comment
    // list then this issue should go away).
    // For some reason the cellText does not seem to be nil when there
    // is no text.
    if ((nil == cellText) || ([cellText length] == 0)) {
        cellText = EMPTY_TEXT; // temporary empty text
    }

    //NSDate *commentDate = [menuItemCommentDictionary objectForKey:@"date"];

    NSString *imageFileName = [menuItemCommentDictionary objectForKey:COMMENT_KEY_IMAGE_FILENAME];

    // If I directly retrieve the icon from the file and display it
    // that way, I get a mess! The image is much too large!!
    UIImage *theIcon = nil;
    if (imageFileName) {
        theIcon = [PersistentStorage retrieveIconFromFile:imageFileName];
    }

    UIFont *cellFont = [UIFont fontWithName:@"Helvetica" size:17.0];

    // Some of the following code modified from:
    //https://stackoverflow.com/questions/1947970/dynamic-calculation-of-uilabel-width-in-uitableviewcell
    // Find the cell for this index path
    UITableViewCell *cell = [self tableView:thisTableView cellForRowAtIndexPath:indexPath];
    //CGFloat cellHeight = cell.frame.size.height;

    // Calculate text size after forcing a layout    
    [cell layoutIfNeeded];
    //CGSize textSize = [cell.textLabel.text sizeWithFont:cellFont constrainedToSize:CGSizeMake(cell.contentView.bounds.size.width, MAXFLOAT) lineBreakMode:cell.textLabel.lineBreakMode];

    NSLog(@"CommentList.heightForRowAtIndexPath: cell.textLabel.bounds.size.width: %d", (int) cell.textLabel.bounds.size.width);

    // In my tests, bounds.size.width is the same as frame.size.width
    NSLog(@"CommentList.heightForRowAtIndexPath: cell.textLabel.frame.size.width: %d", (int) cell.textLabel.frame.size.width);

    // cell.contentView.bounds.size.width gives the full width of the
    // cell contents, which was 287 pixels when I tested it
    if (CommentListDebug) NSLog(@"CommentList.heightForRowAtIndexPath: cell.contentView.bounds.size.width: %d", (int) cell.contentView.bounds.size.width);

    // parameters to CGSizeMake are: width, height
    // the width parameter here is supposed to be the text width;

    CGSize constraintSize;

    if (theIcon) {
        // Start hack for BUG74; 1/29/13
        // The number 27 just works; Is it the width of the
        // accessory button within the cell?
        // cell.contentView.bounds.size.width was 287 when I checked.
        int textWidth = cell.contentView.bounds.size.width - 27 - theIcon.size.width;
        constraintSize = CGSizeMake(textWidth, MAXFLOAT);
        // End hack for BUG74; 1/29/13
    } else {
        constraintSize = CGSizeMake(cell.textLabel.bounds.size.width, MAXFLOAT);
    }

    CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:cell.textLabel.lineBreakMode];

    //NSNumber *iconHeight  = [menuItemCommentDictionary objectForKey:@"imageIconHeight"];

#define LABEL_HEIGHT_EXTRA 20
#define ICON_HEIGHT_EXTRA 10

    int textHeight = labelSize.height + LABEL_HEIGHT_EXTRA;

    if (theIcon) {
    //if ([iconHeight intValue] > 0) {
        // Add 10 EXTRA here to give some white space between icons;
        // with no white space, it can be hard to tell where one icon
        // starts and where another ends, particularly because
        // icons have variable height.
        int iconHeight = ((int) theIcon.size.height) + ICON_HEIGHT_EXTRA;

        /* if (CommentListDebug) */NSLog(@"CommentList.heightForRowAtIndexPath: icon height: %d; icon width: %d", (int) theIcon.size.height, (int) theIcon.size.width);

        // BUG74: 1/28/13; If the text height is taller than the image 
        // height use the text height as the cell height.
        NSLog(@"CommentList.heightForRowAtIndexPath: iconHeight= %d, textHeight= %d", iconHeight, textHeight);

        if (iconHeight >= textHeight) return iconHeight;
        return textHeight;

        //return [iconHeight intValue] + 10;
    } else {
        // No image; use label size for height.
        return textHeight;
    }
}
4

1 回答 1

0

因此,如果我弄错了,请纠正我,但是如果您能够增加单元格的大小(如底部图片),那么一切都会按照您的意愿进行吗?如果是这种情况,您可以覆盖:

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

这将允许您指定您想要的单元格的高度。通过这种方式,您可以设置它们并防止它们剪切底部的文本(如第一张图片)。

于 2013-01-29T19:57:22.293 回答