UICollectionView单元格的子视图不会自动调整大小

45
CollectionView中,一些单元格应该有额外的子视图或图层。可以告诉CollectionView调整其单元格的大小,因此所有内容都需要相应地调整大小。
目前,单元格从包含带有imageview的单元格的nib中初始化;将单元格nib链接到自定义的UICollectionViewCell子类,仅执行init。已勾选自动调整子视图。 CollectionView通过sizeForItemAtIndexPath:中派生并返回的值来告诉单元格调整大小。我已经对FlowLayout进行了子类化,但它只指定了ScrollDirectionInsets
所有这些都很好地运作。问题是:如何向单元格添加子视图/图层,以便它也正确地调整大小?我尝试关闭translatesAutoresizingMaskIntoConstraints添加子视图和图层,但这些不会自动更改大小。还尝试使用代码框架/视图而不是nib。
我现在得到的最好结果是一个cell.contentView.layer子层,我在cellForItemAtIndexPath:中添加;通过存储来自sizeForItemAtIndexPath:的单元格frame.size "手动"调整大小,这不仅丑陋,而且最终导致子层对于不同的单元格具有各种大小。
任何帮助都将不胜感激!

使用自动布局,如果约束设置正确,子视图应该会随着单元格自动扩展。如果您需要更具体的帮助,请描述这个子视图以及您希望它如何扩展。 - rdelmar
感谢您的评论@rdelmar。我对约束条件有一些模糊的感觉,但从未跟进过,所以我没有想到只是关闭它们。现在我已经这样做了,它可以工作了...现在我只需要处理起点,这应该很容易。谢谢! - ceekay
10个回答

88

我刚刚遇到了同样的问题。

当使用UICollectionViewFlowLayoutDelegate方法根据设备和设备方向设置单元格大小时,大小会被正确计算,但子视图不会调整大小以填充新的单元格。结果是一个大的空白单元格,带有小的子视图,这些子视图不能填充单元格的边界/保持与在xib文件中当前值相等的大小。

我通过在awakeFromNib中执行以下操作解决了这个问题:

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    self.contentView.translatesAutoresizingMaskIntoConstraints = YES;
}
在执行这个操作之前,contentView的蒙版是nil

如何处理 Swift 4 - S At

23
*override func awakeFromNib() {
    super.awakeFromNib()

    self.contentView.autoresizingMask.insert(.FlexibleHeight)
    self.contentView.autoresizingMask.insert(.FlexibleWidth)
}

这对我很有用。这段代码需要放在你的子类化UICollectionViewCell.swift文件中(在涉及自定义单元格的代码所在位置)

Swift解决方案*


我怎么能忘记这个。。谢谢! - denis631

8
作为启用AutoResizingMask的替代方案,对于自定义的UICollectionViewLayouts,例如具有可变高度的布局,在其中手动设置一些约束并需要translatesAutoresizingMaskIntoConstraints保持NO,您可以在单元格的layoutSubviews中添加以下内容:
self.contentView.frame = self.bounds;

这个方法解决了我所有自定义集合视图布局在Xcode 6中出现问题的情况。

这个对我有用,但其实没有必要使用多余的CGRectInset - Mazyod

5

在另一个没有xibs的项目中,我子类化了UICollectionViewCell,并采用了以下方式来达到同样的效果:

#import "CVcell.h"

@implementation CVcell

@synthesize cellImage;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        CGFloat cellSize = self.contentView.bounds.size.width;
        cellImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, cellSize, cellSize)];
        [cellImage setClipsToBounds:YES];

        cellImage.translatesAutoresizingMaskIntoConstraints = NO;
        cellImage.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        [self.contentView addSubview:cellImage];

    }
    return self;
}

@end

translatesAutoresizingMaskIntoConstraints设置为“否”,是否意味着它会忽略autoresizingMask?我的印象是,在幕后没有非自动布局,只有模拟旧/替代方式的自动布局。 - Hari Honor

3

在可能的情况下,我总是更喜欢使用autolayout。 但有时,在仅由其superview确定一个视图时,使用frames和bounds只是一种省时的方法。

在UICollectionViewCell的情况下,我将图像设置为单元格的frame + self.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

但当我在collectionView中有不同大小的单元格时,它会弄乱事情,图像有时会采用不同单元格的大小。

所以我转而使用单元格的bounds - 是的,这确实很好用。

所以也许你可以试试这个方法?


3
一个简单的自动布局解决方案是为容器视图设置约束。因此,如果我们有一个带有父视图的图像视图,基本上我们想要告诉子视图(即图像视图)在容器视图上保持前导、尾随、底部和顶部距离为0。如下图所示:Auto layout constraints to resize with parent view

2

@Alfie Hanssen的解决方案(在这里)对我来说没有很好地工作,根据这篇文章

XIB中单元格视图的大小为50 x 50点,这是流式布局中设置的默认单元格大小。即使在Interface Builder中使用这么小的单元格有些困难,最好不要更改默认大小。问题在于Auto Layout将手动设置的大小视为固定大小,并在尝试自动调整单元格高度时生成NSAutoresizingMaskLayoutConstraint错误。

我检查了UICollectionViewCell,并发现在单元格和contentView之间有一个视图,该视图具有内在宽度和高度约束。我只需要更新而不是使用AutoresizingMask,看起来对我有效。

override func layoutSubviews() {
    contentView.superview?.frame = bounds
    super.layoutSubviews()
}

1
我正在以编程方式添加子视图和约束,以下代码适用于我:
lazy var imageView: UIImageView = { [unowned self] in
    let imageView = UIImageView(frame: self.contentView.frame)
    imageView.contentMode = .scaleAspectFill
    imageView.clipsToBounds = true

    return imageView
}() 

func updateCellWith(image: UIImage) {

    contentView.subviews.forEach { $0.removeFromSuperview() }

    contentView.addSubview(imageView)
    imageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0).isActive = true
    imageView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 0).isActive = true
    imageView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: 0).isActive = true
    imageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0).isActive = true

    self.imageView.autoresizingMask.insert(.flexibleHeight)
    self.imageView.autoresizingMask.insert(.flexibleWidth)

    imageView.image = image

}

0
解决方案是关闭单元格xib的自动约束,并在图像视图的自动调整大小中激活灵活的宽度/高度箭头。

关闭约束会导致XIB文件子视图的错位。 - Mansuu....

0
我遇到了同样的问题。在两个布局之间切换时,我的单元格内部的图片(UIImage)没有被重新调整大小。我的单元格是没有xib文件来构建的,并且我为每个CollectionViewCustomLayout使用了两种不同的单元格类。
我用以下代码进行了编程修复:
self.autoresizesSubviews = YES;

在我的UICollectionViewCell子类中。 但是只有当我将图片作为单元格的背景图像添加时,这才对我起作用,就像这样:
cell.backgroundView[[UIImageView alloc] initWithImage: SumDummyImage ];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接