使用 AutoLayout 使 UICollectionViewCell 高度与其内容(所有子视图的总高度)相匹配

Make UICollectionViewCell's height match its content (sum height of all sub views) with AutoLayout

我找到了使 UIView 的高度与其内容匹配的下一个答案

我对其进行了测试,它工作正常(如果故事板中的 UIView 高度大小大于或小于其内容,那么在运行时它会自动调整自身大小以匹配内容)。

但是如果我使用 UICollectionViewCell 而不是 UIView 那么什么都不会改变,单元格的高度永远不会改变,它始终具有我们在故事板属性中的硬编码高度:

我还能做什么?

我在 UIControllerView 中也有 2 个部分(2 列)。 一行中的两个单元格应该具有相同的大小,即使它们的大小内容不同(当使用带有 GridLayoutManager 的 RecyclerView 时,在 Android 中本地实现的东西,非常容易)

更新

它与 UIView 一起工作,因为我将其顶部约束设置为 Safe Are'a top

我不能用 UICollectionViewCell

更新 2

看来我在这个回答上有了一些进步

但是我需要 newFrame.size.height = CGFloat(ceilf(Float(size.height)))

而不是 newFrame.size.width = CGFloat(ceilf(Float(size.width)))

并且当我们使用这个解决方案时,不要对单元格的底部添加任何约束,否则它将不起作用

使用此解决方案我无法真正使用任何边距,否则某些部分在单元格底部变得不可见

我猜这个问题可以解决

您可以尝试在 collectionView Extension 或本机 collectionViewController 中调用此函数 class:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
    {
        //return something like the size. I write you an example how to use it.
        // You can easily change the value according to your stuff contents height.

        return CGSize(width: collectionView.frame.size.width/3, height: 100)
    }

感谢 and

我解决了我的问题

我决定将其中包含所有需要的子视图的 UIView 放入 UICollecitonViewCell

我将 UIView trailing, leading, top 设置为 ICollecitonViewCell 但我没有将 bottom 设置为单元格视图(你应该使用 UIView 中的最新子视图并连接它们的底部,而不是单元格视图)

然后我将 UIView 的引用添加到我的自定义单元格 class 并将其高度用作单元格的高度:

public class MyCustomItemCell: UICollectionViewCell {

    // other child views references ...

    @IBOutlet weak var wrapperView: UIView! // view which contains your other views

    //forces the system to do one layout pass
    var isHeightCalculated: Bool = false

    override public func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
        //Exhibit A - We need to cache our calculation to prevent a crash.
        if !isHeightCalculated {
            setNeedsLayout()
            layoutIfNeeded()
            var newFrame = layoutAttributes.frame
            newFrame.size.height = wrapperView.frame.height // use height of our UIView
            layoutAttributes.frame = newFrame
            isHeightCalculated = true
        }
        return layoutAttributes
    }
}