Как получить автоматический размер макета UICollectionViewCells в iOS 8? (systemLayoutSizeFittingSize возвращает размер с нулевой высотой в iOS 8)

Начиная с iOS 8 [UIColletionViewCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] возвращает размер с высотой 0.

Вот что делает код:

Чтобы определить размер ячейки в UICollectionView в iOS 7 я использую systemLayoutSizeFittingSize: в ячейке, определенной в файле XIB с использованием автоматического макета. Размер зависит от размера шрифта UILabel будучи подвидом UICollectionViewCell в моем XIB-файле. Шрифт метки установлен на UIFontTextStyleBody, Таким образом, размер ячейки в основном зависит от размера шрифта, установленного в iOS 7.

Вот сам код:

+ (CGSize)cellSize {
    UINib *nib = [UINib nibWithNibName:NSStringFromClass([MyCollectionViewCell class]) bundle:nil];

    // Assumption: The XIB file only contains a single root UIView.
    UIView *rootView = [[nib instantiateWithOwner:nil options:nil] lastObject];

    if ([rootView isKindOfClass:[MyCollectionViewCell class]]) {
        MyCollectionViewCell *sampleCell = (MyCollectionViewCell*)rootView;
        sampleCell.label.text = @"foo"; // sample text without bar

        [sampleCell setNeedsLayout];
        [sampleCell layoutIfNeeded];

        return [sampleCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    }

    return CGSizeZero;

}

Он отлично работает в iOS 7, но не в iOS 8. К сожалению, я понятия не имею, почему.

Как я могу получить автоматический размер макета UICollectionViewCells в iOS 8?

PS: используя

 return [sampleCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

вместо

 return [sampleCell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

как кто-то может предложить, не имеет никакого значения.

8 ответов

Решение

Похоже, это официально ошибка: я подал отчет, который был закрыт как дубликат этого

Сообщит, когда выйдет бета 6.

[Обновление: работает корректно в GM-семени iOS 8, и ошибка была закрыта Apple.]

Что вам нужно сделать, это обернуть весь ваш контент в представление контейнера, а затем позвоните:

return [sampleCell.containerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

Ваша ячейка должна выглядеть следующим образом: cell -> containerView -> sub views

Это работает как на ios7, так и на ios8.

Предположительно, на ios8 все, что вам нужно сделать, это установить смету для оценки, и ячейка автоматически автоматически определит размер. Очевидно, что это не работает с бета 6.

Сейчас мы используем обходной путь, скопированный ниже. Надеемся, что эти проблемы будут решены до выхода iOS 8, и мы можем это убрать. (Kludge предполагает знание неявного поведения содержимого AppleView, и мы должны взломать ссылки на выход IB на любые ограничения, которые мы передаем.)

Мы замечаем, что они также удаляют все autoresizingMasks из раскадровок /NIBs во время обновления, что имеет смысл, учитывая, что это должно быть автоматическое расположение, но представления коллекции все еще возвращаются к пружинам и стойкам. Возможно, это было упущено при чистке?

--Dan

/**
 Kludge around cell sizing issues for iOS 8 and deployment to iOS 7 when compiled for 8.  Call this on the collection view cell before it is used, such as in awakeFromNib.  Because this manipulates top-level constraints, any references to such initial constraints, such as from IB outlets, will be invalidated.

 Issue 1: As of iOS 8 Beta 5, systemLayoutSizeFittingSize returns height 0 for a UICollectionViewCell.  In IB, cells have an implicit contentView, below which views placed in IB as subviews of the cell are actually placed.  However, constraints set between these subviews and its superview are placed on the cell, rather than the contentView (which is their actual superview).  This should be OK, as a constraint among items may be placed on any common ancestor of those items, but this is not playing nice with systemLayoutSizeFittingSize.  Transferring those constraints to be on the contentView seems to fix the issue.

 Issue 2: In iOS 7, prior to compiling against iOS 8, the resizing mask of the content view was being set by iOS to width+height.  When running on iOS 7 compiled against iOS 8 Beta 5, the resizing mask is None, resulting in constraints effecting springs for the right/bottom margins.  Though this starts out the contentView the same size as the cell, changing the cell size, as we do in the revealing list, is not tracked by changing it's content view.  Restore the previous behavior.

 Moving to dynamic cell sizing in iOS 8 may circumvent this issue, but that remedy isn't available in iOS 7.
*/
+ (void)kludgeAroundIOS8CollectionViewCellSizingIssues:(UICollectionViewCell *)cell {

    // transfer constraints involving descendants on cell to contentView
    UIView *contentView = cell.contentView;
    NSArray *cellConstraints = [cell constraints];
    for (NSLayoutConstraint *cellConstraint in cellConstraints) {
        if (cellConstraint.firstItem == cell && cellConstraint.secondItem) {
            NSLayoutConstraint *parallelConstraint = [NSLayoutConstraint constraintWithItem:contentView attribute:cellConstraint.firstAttribute relatedBy:cellConstraint.relation toItem:cellConstraint.secondItem attribute:cellConstraint.secondAttribute multiplier:cellConstraint.multiplier constant:cellConstraint.constant];
            parallelConstraint.priority = cellConstraint.priority;
            [cell removeConstraint:cellConstraint];
            [contentView addConstraint:parallelConstraint];
        } else if (cellConstraint.secondItem == cell && cellConstraint.firstItem) {
            NSLayoutConstraint *parallelConstraint = [NSLayoutConstraint constraintWithItem:cellConstraint.firstItem attribute:cellConstraint.firstAttribute relatedBy:cellConstraint.relation toItem:contentView attribute:cellConstraint.secondAttribute multiplier:cellConstraint.multiplier constant:cellConstraint.constant];
            parallelConstraint.priority = cellConstraint.priority;
            [cell removeConstraint:cellConstraint];
            [contentView addConstraint:parallelConstraint];
        }
    }

    // restore auto-resizing mask to iOS 7 behavior
    contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];
}

У меня была такая же проблема для UITableViewCells и iOS 7 (ios8 работает отлично), но решение "Triet Luong" сработало для меня:

return [sampleCell.containerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

Это не ошибка, я уже некоторое время сталкиваюсь с этой проблемой и пробовал разные вещи, ниже я приведу шаги, которые сработали для меня:

1) использовать contentView [sampleCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

2) вы можете создать свой собственный контент-вид и добавить в него вид-вид, не забудьте прикрепить верхний, нижний, левый и правый вид-вид, если вы используете настраиваемый вид содержимого, в супер-вид, если нет Сделайте это, тогда высота будет 0, здесь также в зависимости от ваших требований, которые вы можете. Например, не прикрепляйте нижнюю часть contentView к superView, чтобы высота представления могла изменяться, но закрепление важно и закрепление зависит от ваших требований.

3) правильно установите ограничения в конструкторе интерфейса в зависимости от ваших требований, есть определенные ограничения, которые нельзя добавить в построителе интерфейса, но затем вы можете добавить их в viewDidLoad viewController.

Таким образом, мой ввод в 2 цента состоит в том, что ограничения должны быть правильно установлены в конструкторе интерфейса для systemLayoutSizeFittingSize:UILayoutFittingCompressedSize, чтобы возвращать правильные размеры, это решение, ребята.

Это ошибка в xCode6 и iOS 8 SDK, работающем на устройствах iOS7:) Это почти сломало мой день. Наконец, он работал с приведенным ниже кодом в подклассе UICollectionViewCell. Я надеюсь, что это будет исправлено в следующей версии

- (void)setBounds:(CGRect)bounds {
    [super setBounds:bounds];
    self.contentView.frame = bounds;
}

Может быть, у вас неправильное ограничение, вы должны указать как виртуальный верхний, так и нижний интервал между вашим UIView и contentView, у меня также была эта проблема раньше, потому что я просто указал виртуальный верхний пробел и не указал виртуальный нижний пробел к contentView

Это была ошибка в бета-версиях iOS 8. Наконец это исправлено для iOS 8 ГБ (Build 12A365). Так что для меня теперь это работает с тем же кодом, который я написал для iOS 7. (см. Вопрос)

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