ios 如何使用 FlowLayout 确定 UICollectionView 的高度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13788522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:28:37  来源:igfitidea点击:

How to determine height of UICollectionView with FlowLayout

iosheightuicollectionviewautolayout

提问by Ignatius Tremor

I've got an UICollectionViewwith an UICollectionViewFlowLayout, and i want to calculate its content size (for return in intrinsicContentSizeneeded for adjusting its height via AutoLayout).

我有一个UICollectionViewUICollectionViewFlowLayout,我想计算它的内容大小(用于intrinsicContentSize通过 AutoLayout 调整其高度所需的返回值)。

The problems is: Even if I have a fixed and equal height for all cells, I don't know how many "rows"/lines I have in the UICollectionView. I also can't determine that count by the number of items in my data source, since the cells representing the data items vary in width, so does consequently the number of items I have in one line of the UICollectionView.

问题是:即使我对所有单元格都有固定且相等的高度,我也不知道UICollectionView. 我也无法通过数据源中的项目数来确定该计数,因为表示数据项的单元格的宽度不同,因此我在UICollectionView.

Since I couldn't find any hints on this topic in the official documentation and googling didn't bring me any further, any help and ideas would be appreciated very much.

由于我在官方文档中找不到关于这个主题的任何提示,谷歌搜索也没有给我带来任何进一步的帮助和想法,我们将不胜感激。

回答by Ignatius Tremor

Whoa! For some reason, after hours of research, I now found a pretty easy answer to my question: I was completely searching in the wrong place, digging through all the documentation I could find on UICollectionView.

哇!出于某种原因,经过数小时的研究,我现在找到了一个非常简单的问题的答案:我完全在错误的地方搜索,挖掘了我能在UICollectionView.

The simple and easy solution lies in the underlying layout: Just call collectionViewContentSizeon your myCollectionView.collectionViewLayoutproperty and you get the height and width of the content as CGSize. It's as easy as that.

简单易行的解决方案在于底层布局:只需调用collectionViewContentSize您的myCollectionView.collectionViewLayout属性,即可获得内容的高度和宽度CGSize。就这么简单。

回答by user1046037

In case you are using Auto layout, then you could create a subclass of UICollectionView

如果您使用的是Auto layout,那么您可以创建一个子类UICollectionView

If you use the below the code then you don't have to specify any height constraints for the collection view as it would vary based on the contents of the collection view.

如果您使用下面的代码,那么您不必为集合视图指定任何高度约束,因为它会根据集合视图的内容而变化。

Given below is the implementation:

下面给出的是实现:

@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

回答by lee

At viewDidAppearyou can get it by:

viewDidAppear你可以得到它:

float height = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height;

Maybe when you reload data then need to calculate a new height with new data then you can get it by: add observer to listen when your CollectionViewfinished reload data at viewdidload:

也许当您重新加载数据时然后需要使用新数据计算新高度然后您可以通过以下方式获得它:添加观察者以在您CollectionView完成重新加载数据时监听viewdidload

[self.myCollectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL];

Then add bellow function to get new height or do anything after collectionview finished reload:

然后添加波纹管功能以获取新高度或在 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;    
}

And don't forget to remove observer:

并且不要忘记删除观察者:

[self.myCollectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];

回答by Nick Wood

user1046037 answer in Swift...

user1046037 在 Swift 中回答...

class DynamicCollectionView: UICollectionView {
    override func layoutSubviews() {
        super.layoutSubviews()
        if bounds.size != intrinsicContentSize() {
            invalidateIntrinsicContentSize()
        }
    }

    override func intrinsicContentSize() -> CGSize {
        return self.contentSize
    }
}

回答by Mohammad Sadiq Shaikh

Swift 3 code for user1046037 answer

用户 1046037 答案的 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
    }

}

回答by Wilson

Swift 4

斯威夫特 4

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

  override var intrinsicContentSize: CGSize {
    return collectionViewLayout.collectionViewContentSize
  }
}

回答by Cesare

Swift 4.2

斯威夫特 4.2

class DynamicCollectionView: UICollectionView {
    override func layoutSubviews() {
        super.layoutSubviews()
        if bounds.size != intrinsicContentSize {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        return self.contentSize
    }
}

回答by Er. Vihar

It's too late to answer this question but I have recently gone through this issue.
@lee's above answerhelp me a lot to get my answer. But that answer is limited to objective-cand I was working in swift.
@lee With reference to your answer, allow me to let the swift user get this issue solved easily. For that, please follow below steps:

现在回答这个问题为时已晚,但我最近经历了这个问题。
@lee 的上述答案对我得到答案有很大帮助。但该答案仅限于Objective-c并且我在swift中工作。
@lee 参考您的回答,请允许我让 swift 用户轻松解决此问题。为此,请按照以下步骤操作:

Declare a CGFloatvariable in declaration section:

CGFloat在声明部分声明一个变量:

var height : CGFloat!

At viewDidAppearyou can get it by:

viewDidAppear你可以得到它:

height = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height

Maybe when you reloaddata then need to calculate a new height with new data then you can get it by: addObserverto listen when your CollectionViewfinished reload data at viewWillAppear:

也许当您的reload数据然后需要使用新数据计算新高度时,您可以通过以下方式获取它:addObserverCollectionView完成重新加载数据时监听viewWillAppear

override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(true)
        ....
        ....
        self.shapeCollectionView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.Old, context: nil)
    }

Then add bellow function to get new height or do anything after collectionviewfinished reload:

然后添加波纹管功能以获取新高度或在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
    }

And don't forget to remove observer:

并且不要忘记删除观察者:

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(true)
    ....
    ....
    self.myCollectionView.removeObserver(self, forKeyPath: "contentSize")
}

I hope this will help you to solve your issue in swift.

我希望这将帮助您快速解决您的问题。

回答by HUNG TRAN DUY

This answer is based on @Er. Vihar's answer. You can easily implement the solution by using RxSwift

这个答案基于@Er。维哈尔的回答。您可以使用 RxSwift 轻松实现解决方案

     collectionView.rx.observe(CGSize.self , "contentSize").subscribe(onNext: { (size) in
        print("sizer \(size)")
    }).disposed(by: rx.disposeBag)

回答by Pramodya Abeysinghe

assuming your collectionView is named as collectionViewyou can take the height as follows.

假设您的 collectionView 被命名为collectionView您可以按如下方式获取高度。

let height = collectionView.collectionViewLayout.collectionViewContentSize.height