133

がありUICollectionViewUICollectionViewFlowLayoutそのコンテンツサイズを計算したい(intrinsicContentSizeAutoLayoutを介して高さを調整するために必要なリターンのために)。

問題は次のとおりです。すべてのセルの高さが固定されていても、に「行」/行がいくつあるかわかりませんUICollectionView。また、データアイテムを表すセルの幅が異なるため、データソース内のアイテムの数でそのカウントを判断することはできません。その結果、の1行にあるアイテムの数も異なりますUICollectionView

公式ドキュメントでこのトピックに関するヒントを見つけることができず、グーグルでそれ以上のことはできなかったので、助けやアイデアをいただければ幸いです。

4

13 に答える 13

271

うわあ!なんらかの理由で、何時間もの調査の結果、私は自分の質問に対する非常に簡単な答えを見つけました。私は間違った場所を完全に検索し、見つけたすべてのドキュメントを調べていましたUICollectionView

シンプルで簡単な解決策は、基礎となるレイアウトにありcollectionViewContentSizeます。myCollectionView.collectionViewLayoutプロパティを呼び出すだけで、コンテンツの高さと幅がとして取得されCGSizeます。それはそれと同じくらい簡単です。

于 2012-12-09T15:09:55.207 に答える
42

自動レイアウトを使用している場合は、次のサブクラスを作成できます。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
于 2014-10-07T08:53:47.613 に答える
25

あなたはそれ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];
于 2015-02-07T04:40:53.703 に答える
13

user1046037の回答のためのSwift3コード

import UIKit

class DynamicCollectionView: UICollectionView {

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

    }

    override var intrinsicContentSize: CGSize {
        return contentSize
    }

}
于 2016-11-06T06:33:10.767 に答える
12

user1046037Swiftでの回答...

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

    override func intrinsicContentSize() -> CGSize {
        return self.contentSize
    }
}
于 2016-04-20T15:09:34.917 に答える
9

スウィフト4

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

  override var intrinsicContentSize: CGSize {
    return collectionViewLayout.collectionViewContentSize
  }
}
于 2018-03-23T03:01:15.847 に答える
9

Swift 4.2

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

    override var intrinsicContentSize: CGSize {
        return self.contentSize
    }
}
于 2019-01-09T17:43:57.877 に答える
6

この質問に答えるには遅すぎますが、私は最近この問題を経験しました。
@leeの上記の答えは、私の答えを得るのに大いに役立ちます。しかし、その答えはObjective-cに限定されており、私は迅速に作業していました。
@leeあなたの答えを参考にして、迅速なユーザーがこの問題を簡単に解決できるようにします。そのためには、以下の手順に従ってください。

宣言CGFloatセクションで変数を宣言します。

var height : CGFloat!

あなたはそれviewDidAppearを得ることができます:

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

たぶん、reloadデータが新しいデータで新しい高さを計算する必要があるときは、次の方法で取得addObserverできCollectionViewます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
    }

そして、オブザーバーを削除することを忘れないでください:

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

これが問題を迅速に解決するのに役立つことを願っています。

于 2017-04-19T05:38:30.323 に答える
2

この回答は@Erに基づいています。ビハールの答え。RxSwiftを使用すると、ソリューションを簡単に実装できます。

     collectionView.rx.observe(CGSize.self , "contentSize").subscribe(onNext: { (size) in
        print("sizer \(size)")
    }).disposed(by: rx.disposeBag)
于 2019-10-21T08:24:24.670 に答える
1

@ 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
    }
}
于 2018-03-01T17:28:11.070 に答える
0

reloadDataさらに、高さを取得する前に電話することをお勧めします。

theCollectionView.collectionViewLayout.collectionViewContentSize;
于 2018-10-29T03:25:07.507 に答える
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)
}

スーパービューに対する高さの制約 悪いシミュレーターの結果

セーフエリアに対する高さの制約 良いシミュレーター結果

于 2019-05-06T17:54:38.287 に答える
0

collectionViewの名前がcollectionViewであるとすると、次のように高さを取得できます。

let height = collectionView.collectionViewLayout.collectionViewContentSize.height
于 2019-12-11T16:44:10.087 に答える