Переменная высота ячейки в 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);
    }

}

Надеюсь, поможет.

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