如何将UICollectionView的高度调整为UICollectionView的内容大小的高度?

cha*_*ary 54 ios swift

我想UICollectionView(红色的)缩小到内容大小的高度,在这种情况下UICollectionViewCells(黄色的)因为有很多空的空间.我尝试的是使用:

override func layoutSubviews() {
    super.layoutSubviews()
    if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
        self.invalidateIntrinsicContentSize()
    }
}

override var intrinsicContentSize: CGSize {
    return self.collection.contentSize
}
Run Code Online (Sandbox Code Playgroud)

return self.collection.contentSize总是返回(宽度,0),因此它收缩到高度值30(我在xib文件中为高度设置的值,虽然我有constaint> = 30).

在此输入图像描述

has*_*san 121

我建议如下:

  1. 向集合视图添加高度约束.
  2. 将其优先级设置为999.
  3. 将其常量设置为只在故事板上合理显示的任何值.
  4. 将集合视图的底部相等约束更改为更大或相等.
  5. 将高度约束连接到插座.
  6. 每次在集合视图上重新加载数据时,请执行以下操作:

代码示例:

CGFloat height = myCollectionView.collectionViewLayout.collectionViewContentSize.height
heightConstraint.constant = height
self.view.setNeedsLayout() Or self.view.layoutIfNeeded()
Run Code Online (Sandbox Code Playgroud)

说明:额外,如果您理解,则无需阅读.明显!!

UI将尝试反映所有约束,无论它们的优先级如何.由于高度约束的优先级较低(999),而底部约束的类型大于或等于.每当高度约束常量设置为小于父视图高度的值时,集合视图将等于给定高度,从而实现两个约束.

但是,当高度约束常量设置为大于父视图高度的值时,两个约束都无法实现.因此,只有具有较高优先级的约束才能实现,即较大或相等的底部约束.

以下只是一种体验的猜测.因此,它实现了一个常量.但是,它也试图使误差在其他未被实现优先级较低的约束导致UI 的最低越好.因此,集合视图高度将等于父视图大小.


iOS*_*iOS 16

在 Swift 5 和 Xcode 10.2.1 中

  1. 固定 CollectionView 的高度

  2. 创建 CollectionViewHeight 的出口

    IBOutlet weak var myCollectionViewHeight: NSLayoutConstraint!
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用下面的代码

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let height = myCollectionView.collectionViewLayout.collectionViewContentSize.height
        myCollectionViewHeight.constant = height
        self.view.layoutIfNeeded()
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 完美的解决方案! (2认同)

d4R*_*4Rk 12

我最后通过子类化UICollectionView和重写一些方法,如下所示.

  • 返回self.collectionViewLayout.collectionViewContentSizeintrinsicContentSize确保,总是有正确的尺寸
  • 然后只要它发生变化就可以调用它(比如on reloadData)

码:

override func reloadData() {
    super.reloadData()
    self.invalidateIntrinsicContentSize()
}

override var intrinsicContentSize: CGSize {
    return self.collectionViewLayout.collectionViewContentSize
}
Run Code Online (Sandbox Code Playgroud)

但请注意,如果您显示大量数据,即使它们不适合屏幕,您也会丢失"重复使用单元格".

  • 迄今为止最漂亮的解决方案 - 至少对于我的用例而言。谢谢。它解决了时间问题,布局需要所有其他约束和视图大小来确定内容大小 - 这个就可以了。 (2认同)
  • 实际上 - 我必须将内在大小限制为至少 1 - 绝不是 0 - 才能正确工作。否则,计算中会出现一些小错误,将视图底部切掉几个像素。 (2认同)

Par*_*tel 10

1)设置您的CollectionView的Fix Height。

2)创建此CollectionView高度常量的出口。喜欢 :

IBOutlet NSLayoutConstraint * constHeight;

3)在您的.m文件中添加以下方法:

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    CGFloat height = collectionMenu.collectionViewLayout.collectionViewContentSize.height;
    constHeight.constant = height;
}
Run Code Online (Sandbox Code Playgroud)

  • 这使用 `Swift 5` 和 `Xcode 10.2.1` 工作。谢谢。 (3认同)

Tyt*_*ten 9

这对我来说似乎是最简单的解决方案。

class SelfSizingCollectionView: UICollectionView {
    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    private func commonInit() {
        isScrollEnabled = false
    }

    override var contentSize: CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    override func reloadData() {
        super.reloadData()
        self.invalidateIntrinsicContentSize()
    }

    override var intrinsicContentSize: CGSize {
        return contentSize
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能不需要覆盖 reloadData

  • 这是 iOS 14 上唯一对我有用的东西。谢谢! (2认同)

Bha*_*iya 8

您必须将高度约束设置为等于内容大小

HeightConstraint.constant = collection.contentSize.height 
Run Code Online (Sandbox Code Playgroud)


n13*_*n13 8

采用 d4Rk 的解决方案,这很棒,但在我的情况下,它会不断切断我的集合视图的底部(太短)。我发现这是因为内在内容大小有时为 0,这会导致计算失败。我不知道。我所知道的是这解决了它。

import UIKit

class SelfSizedCollectionView: UICollectionView {
    override func reloadData() {
        super.reloadData()
        self.invalidateIntrinsicContentSize()
    }

    override var intrinsicContentSize: CGSize {
        let s = self.collectionViewLayout.collectionViewContentSize
        return CGSize(width: max(s.width, 1), height: max(s.height,1))
    }

}
Run Code Online (Sandbox Code Playgroud)


Jin*_*lík 6

  1. 子类化 UICollectionView 如下
  2. 删除高度限制(如果有)
  3. 打开内在尺寸

-

class ContentSizedCollectionView: UICollectionView {
    override var contentSize:CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        layoutIfNeeded()            
        return CGSize(width: UIView.noIntrinsicMetric, height: collectionViewLayout.collectionViewContentSize.height)
    }
}
Run Code Online (Sandbox Code Playgroud)