Jak określić wysokość UICollectionView za pomocą FlowLayout
Mam UICollectionView
z UICollectionViewFlowLayout
i chcę obliczyć jego rozmiar zawartości (dla zwrotu w intrinsicContentSize
potrzebnego do regulacji jego wysokości poprzez AutoLayout).
Problem polega na tym, że nawet jeśli mam stałą i równą wysokość dla wszystkich komórek, Nie wiem, ile "wierszy" / linii mam w UICollectionView
. Nie mogę również określić, że liczy się przez liczbę pozycji w moim źródle danych, ponieważ komórki reprezentujące pozycje danych różnią się szerokością, więc w konsekwencji liczba pozycji mam w jednym wierszu UICollectionView
.
Ponieważ nie mogłem znaleźć żadnych wskazówek na ten temat w oficjalnej dokumentacji, a googling nie przyniósł mi nic więcej, każda pomoc i pomysły będą bardzo mile widziane.
8 answers
Whoa! Z jakiegoś powodu, po wielu godzinach badań, znalazłem dość łatwą odpowiedź na moje pytanie: szukałem całkowicie w niewłaściwym miejscu, przekopując się przez całą dokumentację, którą mogłem znaleźć na UICollectionView
.
Proste i łatwe rozwiązanie leży w podstawowym układzie: po prostu wywołaj {[1] } na swojej właściwości myCollectionView.collectionViewLayout
, a otrzymasz wysokość i szerokość zawartości jako CGSize
. To takie proste.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-09 15:09:55
Jeśli używasz Auto layout , możesz utworzyć podklasę UICollectionView
Jeśli używasz poniższego kodu, nie musisz określać żadnych ograniczeń wysokości dla widoku kolekcji, ponieważ różni się ona w zależności od zawartości widoku kolekcji.
Poniżej podano implementację:
@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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-07 08:53:47
W viewDidAppear
możesz go zdobyć przez:
float height = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height;
Może po przeładowaniu danych trzeba obliczyć nową wysokość z nowymi danymi wtedy można ją uzyskać przez:
dodaj observer do odsłuchu, gdy twoje CollectionView
zakończyło reloadowanie danych w viewdidload
:
[self.myCollectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL];
Następnie dodaj funkcję poniżej, aby uzyskać nową wysokość lub zrób cokolwiek po zakończeniu przeładowania 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;
}
I nie zapomnij usunąć obserwatora:
[self.myCollectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-07 04:40:53
User1046037 odpowiedz W Swift...
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if bounds.size != intrinsicContentSize() {
invalidateIntrinsicContentSize()
}
}
override func intrinsicContentSize() -> CGSize {
return self.contentSize
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-19 15:29:26
Swift 3 kod dla user1046037 odpowiedz
import UIKit
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return contentSize
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-06 06:33:10
Jest już za późno, aby odpowiedzieć na to pytanie, ale ostatnio przejrzałem ten problem.
@lee ' s above answer help me a lot to get my answer. Ale ta odpowiedź jest ograniczona do objective-c i pracowałem w swift .
@lee w nawiązaniu do twojej odpowiedzi, pozwól mi pozwolić użytkownikowi swift łatwo rozwiązać ten problem. W tym celu wykonaj poniższe kroki:
Declare a CGFloat
variable in declaration section:
var height : CGFloat!
At viewDidAppear
można go dostać przez:
height = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height
Może Kiedy reload
Dane będą musiały obliczyć nową wysokość z nowymi danymi, możesz je uzyskać przez: addObserver
aby posłuchać, gdy twoje CollectionView
skończy się przeładować dane na viewWillAppear
:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
....
....
self.shapeCollectionView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.Old, context: nil)
}
Następnie dodaj funkcję poniżej, aby uzyskać nową wysokość lub zrób cokolwiek po collectionview
zakończonym przeładowaniu:
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
}
I nie zapomnij usunąć obserwatora:
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(true)
....
....
self.myCollectionView.removeObserver(self, forKeyPath: "contentSize")
}
Mam nadzieję, że to pomoże Ci rozwiązać twój problem w swift.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-06 13:21:34
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
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-23 03:01:15
Wersja Swift @user1046037:
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
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-01 17:28:11