如何使用FlowLayout确定UICollectionView的高度

Ign*_*mor 111 height ios autolayout uicollectionview

UICollectionView有一个UICollectionViewFlowLayout,我想计算它的内容大小(intrinsicContentSize通过AutoLayout调整其高度所需的返回).

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

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

Ign*_*mor 245

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

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

  • scrollViewContentSize和滚动视图的contentSize有什么区别? (8认同)
  • 它可以为谁提供帮助:在此之前我必须做一个“layoutIfNeeded()”,这样我才能让它工作。 (2认同)

use*_*037 35

如果您使用自动布局,那么您可以创建一个子类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
Run Code Online (Sandbox Code Playgroud)

  • 对我不起作用...我在UITableViewCell中使用我的CollectionView,并希望tableview在高度增长,因为集合视图使用iOS8 UITableViewAutomaticDimension增加高度但是我的collectionview保持小:( (11认同)
  • 是的,我将集合视图设置为"不滚动,没有scollbars",然后重新加载它,然后设置tableview的内容.collectionview也是一个子类,它将内容大小作为intrinsicContentSize返回.希望有所帮助! (3认同)
  • 一个重要的事情是在集合视图中禁用滚动和滚动条 (2认同)
  • 和Georg一样的问题,当它应该超过400时,它的高度大约是50px (2认同)

lee*_*lee 21

viewDidAppear你可以得到它:

float height = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height;
Run Code Online (Sandbox Code Playgroud)

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

[self.myCollectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL];
Run Code Online (Sandbox Code Playgroud)

然后添加波纹管功能以获得新高度或在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;    
}
Run Code Online (Sandbox Code Playgroud)

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

[self.myCollectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];
Run Code Online (Sandbox Code Playgroud)


小智 11

user1046037在Swift中回答...

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

    override func intrinsicContentSize() -> CGSize {
        return self.contentSize
    }
}
Run Code Online (Sandbox Code Playgroud)


Moh*_*ikh 10

用户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
    }

}
Run Code Online (Sandbox Code Playgroud)


Wil*_*son 6

斯威夫特4

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

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

  • 我发现它在 iPhone 6/7 plus 和 XR、XS-MAX 上不起作用 (2认同)

Er.*_*har 5

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

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

var height : CGFloat!
Run Code Online (Sandbox Code Playgroud)

viewDidAppear你可以得到它:

height = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height
Run Code Online (Sandbox Code Playgroud)

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

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

然后添加波纹管功能以获取新高度或在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
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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


Ces*_*are 5

斯威夫特4.2

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

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