NSString sizeWithFont:constrainedToSize: вычисление неверной высоты
У меня есть стиль субтитров UITableViewCell, высота которого динамически изменяется в зависимости от длины текста для каждого поля. Проблема в том, что высота textLabel (размер CGSize) не увеличивается, если метка имеет несколько строк.
Странная часть в том, что высота detailTextLabel увеличивается, как и должно быть (CGSize size2). Код для расчета обеих высот идентичен.
Вот моя функция:
-(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];
обновите свой код с этим. Я надеюсь, что это решит вашу проблему. Удачи