Переменная высота ячейки в iOS UITableView с автоматическими ограничениями макета в коде
У меня есть контроллер представления, который имеет экземпляр UITableView и использует автоматические ограничения макета для его визуализации. Я хотел бы иметь переменную высоту ячеек в этом табличном представлении. Я не хочу вычислять высоту ячейки самостоятельно, потому что у меня есть сложное содержимое ячейки, состоящее из нескольких меток и изображений, которые могут варьироваться от ячейки к ячейке. Я верю, что можно позволить ячейке автоматической разметки изменить размеры себя, чтобы она содержала все свои подпредставления (то есть, используя метод меток sizeToFit после назначения им текста?).
У меня есть пользовательский класс ячеек, который использует формат визуальных ограничений автоматического размещения для размещения своих подпредставлений. Я попытался включить предложенный здесь метод и пример его реализации здесь.
Когда я инициализирую табличное представление, я создаю массив с равной длиной строк данных и вычисляю высоту каждой строки, присваивая значения ячейке-прототипу типа MyCustomCell и получая ее высоту, используя эту
[cell systemLayoutSizeFittingSize:UILayoutFittingExpandedSize].height
и сохраняя его в массиве высот, чтобы использовать его позже в методе heightForRowAtIndexPath табличного представления для получения правильной высоты ячейки для отдельных ячеек.
Делая все это, однако, я получаю нечитаемое исключение NSInternalInconsistencyException в xCode с "Не удается найти заголовок исходящей строки для входящей головки MyCustomCell:0xa8a1430.Width, что никогда не должно происходить".
Вот инициализация подпредставлений в моей пользовательской ячейке:
_titleLabel = [[UILabel alloc] init];
_titleLabel.font = [TSTheme boldThemeFontOfSize:TSThemeFontSizeSmall];
_titleLabel.textColor = [[TSTheme sharedTheme] darkTextColor];
_titleLabel.backgroundColor = [UIColor clearColor];
_titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
_titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-CondensedBold" size:19];
_titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self.contentView addSubview:_titleLabel];
_summaryLabel = [[UILabel alloc] init];
_summaryLabel.font = [TSTheme boldThemeFontOfSize:TSThemeFontSizeSmall];
_summaryLabel.backgroundColor = [UIColor clearColor];
_summaryLabel.textColor = [[TSTheme sharedTheme] darkTextColor];
_summaryLabel.translatesAutoresizingMaskIntoConstraints = NO;
_summaryLabel.numberOfLines = 0;
_summaryLabel.preferredMaxLayoutWidth = 250.0f; // required for text wrapping
_summaryLabel.font = [UIFont fontWithName:@"Georgia" size:14];
_summaryLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self.contentView addSubview:_summaryLabel];
_thumbnailView = [[UIImageView alloc] init];
_thumbnailView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:_thumbnailView];
и ограничения для моей пользовательской ячейки следующие
NSDictionary *views = NSDictionaryOfVariableBindings(_titleLabel, _summaryLabel, _thumbnailView);
NSDictionary *metrics = @{@"margin": @"5"};
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(margin)-[_thumbnailView(<=60)]-(margin)-[_titleLabel]-(margin)-|"
options:0
metrics:metrics
views:views]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(margin)-[_thumbnailView]-(margin)-|"
options:0
metrics:metrics
views:views]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(margin)-[_titleLabel]-(0)-[_summaryLabel]"
options:0
metrics:metrics
views:views]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(margin)-[_thumbnailView]-(margin)-[_summaryLabel]-(margin)-|"
options:0
metrics:metrics
views:views]];
3 ответа
Я столкнулся с этим, когда использовал ячейку табличного представления, которая была добавлена непосредственно в качестве прототипа для UITableView в раскадровке, и использовал dequeueReusableCellWithIdentifier: чтобы получить ячейку для кэширования высот.
Если я переместил ячейку в отдельный наконечник, то он создал экземпляр ячейки для определения высоты непосредственно из наконечника, и проблема исчезла.
Затем вы можете зарегистрировать перо с помощью UITableView. Надеюсь это поможет.
- Назначить и реализовать источник данных tableview и делегировать
- приписывать
UITableViewAutomaticDimension
в rowHeight и по оценкам RowHeight - Реализуйте методы делегата / источника данных (т.е.
heightForRowAt
и вернуть значениеUITableViewAutomaticDimension
к этому)
-
Цель C:
// in ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
@property IBOutlet UITableView * table;
@end
// in ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.table.dataSource = self;
self.table.delegate = self;
self.table.rowHeight = UITableViewAutomaticDimension;
self.table.estimatedRowHeight = UITableViewAutomaticDimension;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
Swift:
@IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Don't forget to set dataSource and delegate for table
table.dataSource = self
table.delegate = self
// Set automatic dimensions for row height
table.rowHeight = UITableViewAutomaticDimension
table.estimatedRowHeight = UITableViewAutomaticDimension
}
// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Для экземпляра метки в UITableviewCell
- Установить количество строк = 0 (& режим разрыва строки = обрезать хвост)
- Установите все ограничения (сверху, снизу, справа налево) относительно его контейнера superview/ cell.
- Необязательно: Установите минимальную высоту для метки, если вы хотите, чтобы минимальная вертикальная область была покрыта меткой, даже если данных нет.
Примечание. Если у вас более одной метки (UIElements) с динамической длиной, которую следует отрегулировать в соответствии с размером ее содержимого: настройте "Приоритет содержания и сопротивления сжатию" для меток, которые вы хотите расширить / сжать с более высоким приоритетом.
Я использовал этот код для динамического вычисления длины строки, потому что содержание каждого было разным:
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ // Hacer que el tamaño de la celda sea variable dependiendo del tamaño del texto a mostrar
NoticiaAsignatura_DTO *rowData = [[NoticiaAsignatura_DTO alloc] init];
rowData = [self.listaNoticias objectAtIndex:[indexPath row]];
NSString *text = rowData.title;
text = [text stringByAppendingString:@"\n"];
text = [text stringByAppendingString: rowData.publish_date_ansi];
text = [text stringByAppendingString:@"\n\n"];
text = [text stringByAppendingString:rowData.content];
text = [text stringByAppendingString:@"\n\n"];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
CGSize constraint = CGSizeMake(700,200000.0);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
return size.height + (CELL_CONTENT_MARGIN * 2);
}
else{
CGSize constraint = CGSizeMake(300,200000.0);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_PHONE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
NSLog(@"Size: %f ", size.height);
return size.height + (CELL_CONTENT_MARGIN * 2);
}
}
Надеюсь, поможет.