1

テーブル セルに多くのテキストと画像がある場合、テーブル セルの高さを決定する際に問題が発生します。しかし、問題は文脈依存であり、使用されるテキストの種類によって異なります。問題を説明し、セルの書式設定とセルの高さの決定に使用しているコードを示します。セルの左側に画像がある場合、画像とテキストの最大高さからセルの高さを取得しています。問題は、すべての状況で文字の高さが正しく計算されないことです。以下では、下のセルに次のテキストがあります。

“P 154 ベトナムの家庭料理: とても良い!! スパイスをブレンドしてペースト状にすると、うまくいきました。ズッキーニの残りのソースを使ってグリルしました。うまくいきました。厚いポークチョップ; 450 ~ 525 で 35 分間調理します。」

テーブル ビューが一番下までスクロールされます。ご覧のとおり、テキストの下部は存在しません (「450 ~ 525 で 35 分間加熱」)。実際に起こっていることは、テキスト幅が正しく決定されていないということです。以下では、テキスト幅は cell.textLabel.bounds.size.width: 234 ピクセルとして計算されています。これに基づいて、テキストの高さが正しく計算されません。 不完全なテキストを表示するシミュレーターのスクリーン グラブ

ただし、アクセサリ ボタン (「>」) を押して次のビューに移動し、そのビューから (ナビゲーション コントローラーで「戻る」ボタンを使用して) 戻ると、通常は次のように変更されたテーブル表示が表示されます (ただし、場合によっては、残りのテキストなしで上記のビューを取得します): 完全なテキストを表示するシミュレーターのスクリーン グラブ

この場合、テーブル ビューが 2 回目に表示されるときに、テキストの幅は cell.textLabel.bounds.size.width: 163 ピクセルとして計算されます。2 つのテキスト幅の差 (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 内の正しい幅に強制することでした。ただし、これは確かにハックです。より良い解決策が欲しいです。アイデア?

コード

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 に答える