UICollectionView 单元格子视图不调整大小

Posted

技术标签:

【中文标题】UICollectionView 单元格子视图不调整大小【英文标题】:UICollectionView cell subviews do not resize 【发布时间】:2013-02-24 12:50:18 【问题描述】:

CollectionView 中,一些单元格应该有一个额外的子视图或层。可以告诉CollectionView 调整其单元格的大小,因此所有内容都需要适当地调整大小。

目前,该单元格是从一个包含带有 imageview 的单元格的 nib 初始化的;单元格笔尖链接到自定义 UICollectionViewCell 子类,该子类仅执行 init。 Autoresize 子视图被选中。

CollectionView 被告知通过在sizeForItemAtIndexPath: 中派生和返回的值来调整单元格的大小。我对 FlowLayout 进行了子类化,但它只指定了 ScrollDirectionInsets

所有这些都运行良好。问题:如何将子视图/图层添加到单元格,以便它也正确调整大小?我尝试在关闭translatesAutoresizingMaskIntoConstraints 的情况下添加子视图和图层,但它们根本不会自动更改大小。还尝试使用代码框架/视图而不是笔尖。

我现在得到的最好的是一个cell.contentView.layer 子层,我在cellForItemAtIndexPath: 中添加了它;这是通过存储来自sizeForItemAtIndexPath: 的单元格的frame.size 来“手动”调整大小的,这不仅丑陋,而且最终导致子层对于不同的单元格具有不同的大小。

任何帮助表示赞赏!

【问题讨论】:

使用自动布局,如果约束设置正确,子视图应自动随单元格展开。您需要描述此子视图,以及如果您需要更具体的帮助,您希望它如何扩展。 感谢@rdelmar 的评论。我对约束有一种模糊的感觉,但从未跟进,所以我没有想到只是将它们关闭。做到了,它的工作原理......现在我只需要处理应该很容易的起源。谢谢! 【参考方案1】:

我遇到了同样的问题。在两种布局之间切换并没有调整单元格内的图片(UIImage)大小。我的细胞在没有 xib 的情况下构建。我为每个 CollectionViewCustomLayout 使用了两个不同的单元格类。

我以编程方式解决了这个问题:

self.autoresizesSubviews = YES;

在我的 UICollectionViewCell 子类中。

但这仅对我有用,方法是将图片添加为单元格背景图片,如下所示:

cell.backgroundView[[UIImageView alloc] initWithImage: SumDummyImage ];

【讨论】:

【参考方案2】:

我正在以编程方式添加 subView 和约束,以下代码适用于我:

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


【讨论】:

【参考方案3】:

根据this article,@Alfie Hanssen 解决方案 (here) 不适用于我:

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

我检查了 UICollectionViewCell,发现单元格和 contentView 之间有一个视图,并且该视图具有固有的宽度和高度约束。而不是 AutoresizingMask 我只是更新如下,似乎对我有用。

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

【讨论】:

【参考方案4】:
*override func awakeFromNib() 
    super.awakeFromNib()

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

这对我有用.. 此代码位于您的子类 UICollectionViewCell.swift 文件中(涉及自定义单元格的代码所在的位置)

快速解决方案*

【讨论】:

我怎么会忘记这个...谢谢!【参考方案5】:

作为启用 AutoResizingMask 的替代方法,对于具有可变高度的自定义 UICollectionViewLayouts,例如您手动设置一些约束并且需要 translatesAutoresizingMaskIntoConstraints 保持 NO,您可以将以下内容添加到单元格中的 layoutSubviews:

self.contentView.frame = self.bounds;

这可以解决我在 Xcode 6 中出现问题的所有自定义集合视图布局。

【讨论】:

+1 这对我有用,但真的不需要多余的CGRectInset【参考方案6】:

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

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

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

- (void)awakeFromNib

    [super awakeFromNib];

    self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    self.contentView.translatesAutoresizingMaskIntoConstraints = YES;

在执行此操作之前,contentView 掩码为nil

【讨论】:

感谢@alfie-hanssen,您的解决方案有助于解决使用自定义 UICollectionViewLayout 从 Xcode5 切换到 Xcode6 时出现的错误 谢谢,很高兴它有帮助! 谢谢。一旦我开始使用 Xcode 6 GM 构建,这个问题就出现在 ios 7 设备上,并将它添加到我的所有集合单元子类中修复了它。 谢谢你,阿尔菲!当我开始使用 XCode 6 GM 构建时,iOS 7 设备也存在同样的问题。 这里是同一问题的另一个答案的链接:***.com/a/25768887/2631081【参考方案7】:

一个简单的自动布局解决方案是为容器视图设置约束。

因此,如果我们有一个带有父视图的图像视图,我们基本上希望告诉子视图(图像视图)与容器视图保持 0 的前导、尾随、底部和顶部空间距离。

【讨论】:

【参考方案8】:

如果可能,我总是更喜欢自动布局。 但有时,当视图仅由其父视图直接确定时,使用框架和边界会节省时间。

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

但是当我在 collectionView 中有不同大小的单元格时,它会搞砸事情,并且图像有时会占用不同单元格的大小。

所以我转而使用细胞边界,并且 - 确实效果很好。

那么不妨试试看?

【讨论】:

【参考方案9】:

在另一个没有 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 设置为NO 意味着它将忽略autoresizingMask?我的印象是,在非自动布局中没有这样的东西,只有模仿旧/替代方式的自动布局。【参考方案10】:

解决方案是关闭单元格 xib 的 AutoConstraints,并在图像视图的 AutoResize 中激活灵活的宽度/高度箭头。

【讨论】:

关闭约束会导致 xib 文件子视图错位

以上是关于UICollectionView 单元格子视图不调整大小的主要内容,如果未能解决你的问题,请参考以下文章

当边界 UICollectionView 更改时调整单元格大小

配置 UICollectionView 以保持相同的单元格视图

UITableview 单元格子视图的高度比单元格大

UICollectionView 从另一个视图控制器返回时重复单元格

如何在一个视图中添加多个部分 UICollectionView 单元格

如何根据 UICollectionView 中有多少单元格来更改视图的大小