我有UICollectionView
UICollectionViewFlowLayout
,我想计算其内容大小(通过AutoLayout调整其高度所需的intrinsicContentSize
返回)。
问题是:即使我对所有单元格都有一个固定且相等的高度,我也不知道UICollectionView
中有多少“行”/行。我也无法通过数据源中的项目数来确定计数,因为表示数据项的单元格的宽度不同,因此我在UICollectionView
的一行中的项目数也是如此。 / p>
由于我在官方文档中找不到关于此主题的任何提示,谷歌搜索没有给我带来任何进一步的帮助和想法,我们将非常感激。
答案 0 :(得分:239)
哇!出于某种原因,经过几个小时的研究,我现在找到了一个非常简单的问题答案:我在错误的地方搜索,挖掘了我在UICollectionView
找到的所有文档。
简单易用的解决方案在于底层布局:只需在collectionViewContentSize
属性上调用myCollectionView.collectionViewLayout
,即可获得内容的高度和宽度CGSize
。就这么简单。
答案 1 :(得分:34)
如果您使用自动布局,则可以创建UICollectionView
如果您使用下面的代码,那么您不必为集合视图指定任何高度约束,因为它会根据集合视图的内容而有所不同。
以下是实施:
@interface DynamicCollectionView : UICollectionView
@end
@implementation DynamicCollectionView
- (void) layoutSubviews
{
[super layoutSubviews];
if (!CGSizeEqualToSize(self.bounds.size, [self intrinsicContentSize]))
{
[self invalidateIntrinsicContentSize];
}
}
- (CGSize)intrinsicContentSize
{
CGSize intrinsicContentSize = self.contentSize;
return intrinsicContentSize;
}
@end
答案 2 :(得分:19)
在viewDidAppear
您可以通过以下方式获取:
float height = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height;
也许当您重新加载数据时,需要使用新数据计算新高度,然后您可以通过以下方式获取:
添加观察者,以便在CollectionView
完成重新加载数据时viewdidload
[self.myCollectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL];
然后添加波纹管功能以获得新高度或在collectionview完成重新加载后执行任何操作:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
//Whatever you do here when the reloadData finished
float newHeight = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height;
}
不要忘记删除观察者:
[self.myCollectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];
答案 3 :(得分:11)
用户104437回答Swift ...
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if bounds.size != intrinsicContentSize() {
invalidateIntrinsicContentSize()
}
}
override func intrinsicContentSize() -> CGSize {
return self.contentSize
}
}
答案 4 :(得分:8)
用户104437回答的Swift 3代码
import UIKit
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return contentSize
}
}
答案 5 :(得分:3)
现在回答这个问题为时已晚,但我最近已经解决了这个问题。
@ lee' s above answer帮我解决了很多问题。但答案仅限于 objective-c ,而我正在 swift 工作。
@lee参考你的回答,请允许我让快速用户轻松解决这个问题。为此,请遵循以下步骤:
在声明部分声明CGFloat
变量:
var height : CGFloat!
在viewDidAppear
您可以通过以下方式获取:
height = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height
也许当您reload
数据需要使用新数据计算新高度时,您可以通过addObserver
获取它,以便在CollectionView
完成重新加载{{1}数据时进行监听}}:
viewWillAppear
然后添加波纹管功能以获得新高度或在override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
....
....
self.shapeCollectionView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.Old, context: nil)
}
完成重新加载后执行任何操作:
collectionview
不要忘记删除观察者:
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
let newHeight : CGFloat = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height
var frame : CGRect! = self.myCollectionView.frame
frame.size.height = newHeight
self.myCollectionView.frame = frame
}
我希望这可以帮助您快速解决您的问题。
答案 6 :(得分:3)
Swift 4
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return collectionViewLayout.collectionViewContentSize
}
}
答案 7 :(得分:1)
Swift 4.2
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if bounds.size != intrinsicContentSize {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return self.contentSize
}
}
答案 8 :(得分:0)
@ user1046037的Swift版本:
public class DynamicCollectionView: UICollectionView {
override public func layoutSubviews() {
super.layoutSubviews()
if !bounds.size.equalTo(intrinsicContentSize) {
invalidateIntrinsicContentSize()
}
}
override public var intrinsicContentSize: CGSize {
let intrinsicContentSize: CGSize = contentSize
return intrinsicContentSize
}
}
答案 9 :(得分:0)
此外:您最好先致电reloadData
,然后再通过:myCollectionView.collectionViewLayout.collectionViewContentSize
答案 10 :(得分:0)
Swift 4.2,Xcode 10.1,iOS 12.1:
由于某种原因,collectionView.contentSize.height
的显示尺寸小于我的收藏夹视图的已解析高度。首先,我使用的是相对于超级视图高度的1/2的自动布局约束。 要解决此问题,我将约束更改为相对于视图的“安全区域”。
这使我可以使用collectionView.contentSize.height
设置单元格高度以填充收藏视图:
private func setCellSize() {
let height: CGFloat = (collectionView.contentSize.height) / CGFloat(numberOfRows)
let width: CGFloat = view.frame.width - CGFloat(horizontalCellMargin * 2)
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: width, height: height)
}
之前
之后
答案 11 :(得分:0)
此答案基于@Er。维哈尔的答案。您可以使用RxSwift轻松实现该解决方案
collectionView.rx.observe(CGSize.self , "contentSize").subscribe(onNext: { (size) in
print("sizer \(size)")
}).disposed(by: rx.disposeBag)
答案 12 :(得分:0)
假设您的collectionView命名为 collectionView ,您可以按照以下方式进行调整。
let height = collectionView.collectionViewLayout.collectionViewContentSize.height