如何使 collectionViewCell 仅按高度自动调整大小?

How make a collectionViewCell auto size only by height?

我使用了 collectionView 的自动调整流布局的功能

self.flow = [[UICollectionViewFlowLayout alloc] init];
self.flow.scrollDirection = UICollectionViewScrollDirectionVertical;
self.flow.sectionInset = UIEdgeInsetsZero;
self.flow.estimatedItemSize = CGSizeMake(320, 48);

我想让单元格按 CollectionView 的全宽宽度填充 (widthCell=widthCollectionView)

但我得到了整个尺寸的自动调整工作。我尝试使用 Content Compression/Hugging Priority - 无效。

CollectionView 的宽度等于 320px,我得到了标签内容大小的单元格大小。

我的手机看起来像

水平约束:H:|-8-[img(48)]-8-[label]-8-|

如何使自动调整大小仅适用于垂直而不适用于水平?

我找到了解决方案。

CollectionViewCell 有一个委托 preferredLayoutAttributesFittingAttributes

因此,此函数为您提供 layoutAttributes 设置为 estimatedItemSize

你需要做下一步(身高)

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    UICollectionViewLayoutAttributes *attr = [super preferredLayoutAttributesFittingAttributes:layoutAttributes]; //Must be called
    CGRect frame = attr.frame;
    frame.size.width = layoutAttributes.size.width; //Key here
    attr.frame = frame;
    return attr;
}

同样,您可以选择尺寸和宽度,因此高度保持不变 (frame.size.height = layoutAttributes.size.height)。

如果只是复制layoutAttributes并改变width,是没有效果的!

必须调用super.

其实你说的是约束优先级的问题。

要解决优先级约束问题,您应该以编程方式或直接从 InterFace Builder 更新 imageView Leading priority 999label Trailing 优先级 999

通过使用我已经实施的 KVConstraintExtensionsMaster 以编程方式更新优先级,以更新任何没有 IBOutlet reference Autolayout 约束的约束。

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell1" forIndexPath:indexPath];

    [cell.imageView changeAppliedConstraintPriority:999 forAttribute:NSLayoutAttributeLeading];
    [cell.label changeAppliedConstraintPriority:999 forAttribute:NSLayoutAttributeTrailing];

    return cell;
}

之后你需要计算单元格的唯一高度

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
     CGFloat width  = CGRectGetWidth(collectionView.bounds);
     CGFloat height  =  /* do here some calculation for height */
     return CGSizeMake(width, height);;
}

Dmitry Nelepov在swift.

中的解决方案

Swift 4

override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    let attr = super.preferredLayoutAttributesFitting(layoutAttributes)
    var frame = attr.frame
    frame.size.width = layoutAttributes.size.width //Key here
    attr.frame = frame
    return attr
}