IOS 7/8 UITableView Cell: два UILabels с динамической высотой с автоматической компоновкой для переменной высоты строки

Таким образом, я могу настроить динамический размер высоты с помощью автоматического макета, когда у меня есть только одна метка, которая изменяет высоту в зависимости от длины строки. Моя проблема в том, что если я добавлю еще один UILabel, который должен сделать то же самое, все не получится.

Я устанавливаю как приоритет Content Hugging, так и сопротивление сжатия 1000 для обоих == Я получаю предупреждения о двусмысленности

Если я устанавливаю Content Hugging (Вертикальный) для второго UILabel на 999 или 250, тогда он отлично работает, но только если вторая метка имеет 2 или более строк. Если вторая метка пуста или имеет только одну строку, heightForRowAtIndexPath systemLayoutSizeFittingSize: высота UILayoutFittingCompressedSize возвращает большие значения, а ячейки имеют большие пробелы.

Я также играл с Intrinsic Size: Default или Placeholder (с парой высот и ширины), но это тоже не помогает.

Какие-либо предложения о том, что можно сделать?

Ответы

Ответ 1

Наконец-то я работал. Решение было для меня явно установить предпочтительную ширину на текущую ширину кадра. Таким образом, в основном проверка флажка Явная в ярлыке > Предпочтительная ширина в Инспекторе размеров.

ref: http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout загрузите образец кода и посмотрите настройку раскадровки.

Ответ 2

Для меня это взяло комбинацию нескольких вещей.

  • Кроме того, чтобы обеспечить правильное обжатие содержимого и сопротивление
  • Мне пришлось сделать подкласс UILabel для обработки предпочтительнойMaxLayoutWidth метки
  • и исправить ошибку в intrinsicContentSize, а также

Подкласс UILabel выглядит следующим образом:

@implementation LabelDynamicHeight

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.preferredMaxLayoutWidth = self.frame.size.width;

    [super layoutSubviews];
}

- (void)setBounds:(CGRect)bounds
{
    [super setBounds:bounds];

    if (self.numberOfLines == 0)
    {
        CGFloat boundsWidth = CGRectGetWidth(bounds);
        if (self.preferredMaxLayoutWidth != boundsWidth)
        {
            self.preferredMaxLayoutWidth = boundsWidth;
            [self setNeedsUpdateConstraints];
        }
    }
}

- (CGSize)intrinsicContentSize
{
    CGSize size = [super intrinsicContentSize];

    if (self.numberOfLines == 0)
    {
        // There a bug where intrinsic content size may be 1 point too short
        size.height += 1;
    }

    return size;
}

@end

Помимо этого вызова layoutIfNeeded в ячейке перед тем, как получить высоту в tableView heightForRowAtIndexPath:, необходимо сделать ограничения, прежде чем использовать метод systemLayoutSizeFittingSize: в contentView. Выглядит так:

- (CGFloat)tableView:( UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = ...;
    CGFloat height = cell.frame.size.height;
    if (cell.dynamicHeight)
    {
        // https://stackoverflow.com/a/26351692/1840269
        [cell layoutIfNeeded];
        height = cell.frame.size.height;

        CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
        if (size.height > height)
            height = size.height;
    }
    return height;
}

Литература:

Ответ 3

Для меня настройка приоритета сжатия содержимого и приоритета сжатия содержимого ниже, чтобы один из элементов работал так, как ожидалось.