NSString sizeWithFont:constrainedToSize: вычисление неверной высоты

У меня есть стиль субтитров UITableViewCell, высота которого динамически изменяется в зависимости от длины текста для каждого поля. Проблема в том, что высота textLabel (размер CGSize) не увеличивается, если метка имеет несколько строк.

http://s10.postimg.org/6urher7s9/text_Label.png

Странная часть в том, что высота detailTextLabel увеличивается, как и должно быть (CGSize size2). Код для расчета обеих высот идентичен.

http://s21.postimg.org/m0af4gyw7/detail.png

Вот моя функция:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    SETLISTFMNS0Song *song = [[[selectedSetlist.sets objectAtIndex:indexPath.section] songs]objectAtIndex:indexPath.row];
    CGSize size = [song.name sizeWithFont:[UIFont fontWithName:setlistFont size:labelFontSize] constrainedToSize:CGSizeMake(self.setsTable.bounds.size.width, CGFLOAT_MAX)];
    NSLog(@"Label: \"%@\" \tLabel Size: %f W %f H", song.name, size.width, size.height);

    NSMutableString *detail;
    if ([song cover]) {
        detail = [[NSMutableString alloc] initWithFormat:@"(%@ cover)", [[song cover] name]];
    }
    if ([song with]) {
        if (!detail) {
            detail = [[NSMutableString alloc] initWithFormat:@"(with %@)", [[song with] name]];
        }
        else {
            [detail appendFormat:@" (with %@)", [[song with] name]];
        }
    }
    if ([song info]) {
        if (!detail) {
            detail = [[NSMutableString alloc] initWithFormat:@"(%@)", [song info]];
        }
        else {
            [detail appendFormat:@" (%@)", [song info]];
        }
    }

    if (detail.length != 0) {
        CGSize size2 = [detail sizeWithFont:[UIFont fontWithName:setlistFont size:detailFontSize] constrainedToSize:CGSizeMake(self.setsTable.bounds.size.width, CGFLOAT_MAX)];
        size.height += size2.height;
        NSLog(@"Detail Label: \"%@\" \tDetail Label Size: %f W %f H", detail, size2.width, size2.height);
    }

    return size.height + 5;
}

Я также устанавливаю оба свойства numberOfLines textLabel в 0 в cellForRowAtIndexPath для поддержки нескольких строк:

cell.textLabel.numberOfLines = 0;
cell.detailTextLabel.numberOfLines = 0;

ОБНОВЛЕНИЕ: Благодаря @josh теперь я понимаю, почему это происходит. У меня были ограничения ширины, равные ширине UITableView, которая слишком широка. Кто-нибудь знает, как найти ширину UILabel до его создания? ХА!

Спасибо!

2 ответа

Решение

Как долго вы рассчитываете размер строк? Я спрашиваю, потому что ты sizeWithFont:constrainedToSize: Функция ограничена на всю ширину ячейки, но ваши метки, вероятно, не на всю ширину ячейки.

Я подозреваю, что происходит song.info достаточно короток, чтобы он уместился на одной строке, если бы строка была на всю ширину ячейки, и чтобы ваша песня detail достаточно долго, чтобы вычислить правильное количество строк, но не так долго, чтобы превысить вычисленную высоту.

Все это говорит, я думаю, что вам нужно выяснить ширину textLabel а также detailTextLabel и установите ваши ограничения на эти значения.

Обновление - способ расчета ширины этикетки

Поскольку ширина меток внутри ячейки зависит от ширины ячейки, и поскольку ячейки не создаются в данный момент heightForRowAtIndexPath: называется, нам нужно найти способ узнать ширину меток, прежде чем они будут установлены. Единственный способ сделать это - установить ширину самостоятельно. Вот как бы я это сделал:

MyCell.h

#import <UIKit/UIKit.h>

@interface MyCell : UITableViewCell

+ (CGFloat)textLabelWidthForCellOfWidth:(CGFloat)cellWidth;

@end

MyCell.m

#import "MyCell.h"

@implementation MyCell

- (void)layoutSubviews {
    [super layoutSubviews];

    CGRect frame = self.textLabel.frame;
    frame.size.width = [MyCell textLabelWidthForCellOfWidth:self.frame.size.width];
    self.textLabel.frame = frame;
}

+ (CGFloat)textLabelWidthForCellOfWidth:(CGFloat)cellWidth {
    // This calculation can be as complex as necessary to account for all elements that affect the label
    return cellWidth - 20;
}

@end

Тогда в вашем heightForRowAtIndexPath: В реализации вы можете вызвать тот же метод класса:

CGFloat labelWidth = [MyCell textLabelWidthForCellOfWidth:self.tableView.frame.size.width]; // Since non-grouped cells are the full width of the tableView
CGSize size2 = [detail sizeWithFont:[UIFont fontWithName:setlistFont size:detailFontSize] constrainedToSize:CGSizeMake(labelWidth, CGFLOAT_MAX)];

Вы должны создать отдельный метод класса (+) для каждой метки, на которую нужно сослаться.

Глядя на ваш код, я обнаружил, что вам не хватает определения "lineBreakMode".

CGSize theSize = [song.name sizeWithFont:[UIFont fontWithName:setlistFont size:labelFontSize] constrainedToSize:CGSizeMake(self.setsTable.bounds.size.width, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];

обновите свой код с этим. Я надеюсь, что это решит вашу проблему. Удачи

Другие вопросы по тегам