我试图得到自我大小UICollectionViewCells工作与自动布局,但我似乎不能让单元格大小自己的内容。我很难理解如何从单元格的contentView内的内容更新单元格的大小。

下面是我尝试过的设置:

自定义UICollectionViewCell,在它的contentView中有一个UITextView。 UITextView的滚动被禁用。 contentView的水平约束是:"H:|[_textView(320)]",也就是说UITextView被固定在单元格的左边,显式宽度为320。 contentView的垂直约束是:"V:|-0-[_textView]",也就是说UITextView固定在单元格的顶部。 UITextView有一个高度约束设置为常数,UITextView报告将适合文本。

下面是单元格背景设置为红色,UITextView背景设置为蓝色时的效果:

我把我一直在GitHub上玩的项目放在这里。


当前回答

更新更多信息:

If you use flowLayout.estimatedItemSize, suggest use iOS8.3 later version. Before iOS8.3, it will crash [super layoutAttributesForElementsInRect:rect];. The error message is *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil' Second, in iOS8.x version, flowLayout.estimatedItemSize will cause different section inset setting did not work. i.e. function: (UIEdgeInsets)collectionView:layout:insetForSectionAtIndex:.

其他回答

编辑11/19/19:对于iOS 13,只使用UICollectionViewCompositionalLayout估计高度。不要浪费时间处理这个坏的API。

在与此斗争了一段时间后,我注意到,如果你不禁用滚动,调整大小对UITextViews不起作用:

let textView = UITextView()
textView.scrollEnabled = false

上面的示例方法不能编译。以下是更正后的版本(但未经测试是否有效)。

override func preferredLayoutAttributesFittingAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes 
{
    let attr: UICollectionViewLayoutAttributes = layoutAttributes.copy() as! UICollectionViewLayoutAttributes

    var newFrame = attr.frame
    self.frame = newFrame

    self.setNeedsLayout()
    self.layoutIfNeeded()

    let desiredHeight: CGFloat = self.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
    newFrame.size.height = desiredHeight
    attr.frame = newFrame
    return attr
}

在iOS 10+中,这是一个非常简单的2步过程。

Ensure that all your cell contents are placed within a single UIView (or inside a descendant of UIView like UIStackView which simplifies autolayout a lot). Just like with dynamically resizing UITableViewCells, the whole view hierarchy needs to have constraints configured, from the outermost container to the innermost view. That includes constraints between the UICollectionViewCell and the immediate childview Instruct the flowlayout of your UICollectionView to size automatically yourFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

内容查看主播奥秘:

在一个奇怪的例子中

    contentView.translatesAutoresizingMaskIntoConstraints = false

不会起作用。在contentView中添加了四个显式的锚,它工作了。

class AnnoyingCell: UICollectionViewCell {
    
    @IBOutlet var word: UILabel!
    
    override init(frame: CGRect) {
        super.init(frame: frame); common() }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder); common() }
    
    private func common() {
        contentView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            contentView.leftAnchor.constraint(equalTo: leftAnchor),
            contentView.rightAnchor.constraint(equalTo: rightAnchor),
            contentView.topAnchor.constraint(equalTo: topAnchor),
            contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])
    }
}

像往常一样

    estimatedItemSize = UICollectionViewFlowLayout.automaticSize

在你的布局:UICollectionViewFlowLayout

谁知道呢?也许能帮到别人。

信贷

https://www.vadimbulavin.com/collection-view-cells-self-sizing/

无意中发现了这个技巧——在其他1000篇文章中从未见过。

对丹尼尔·加拉斯科的回答做了一些关键的修改,解决了我所有的问题。不幸的是,我还没有足够的声誉来直接评论。

在第一步,当使用自动布局时,简单地添加一个单亲UIView到单元格。单元格内的所有东西都必须是父视图的子视图。这解决了我所有的问题。虽然Xcode会自动为UITableViewCells添加这个,但它不会(但应该)为UICollectionViewCells添加这个。根据文件:

要配置单元格的外观,请在contentView属性的视图中添加将数据项的内容作为子视图显示所需的视图。不要直接向单元格本身添加子视图。

然后完全跳过步骤3。这是不需要的。