Как определить высоту UICollectionView с FlowLayout
у меня есть UICollectionView с UICollectionViewFlowLayout, и я хочу вычислить его размер содержимого (для возврата в intrinsicContentSize необходимый для регулировать свою высоту через AutoLayout).
проблемы: даже если у меня есть фиксированная и равная высота для всех ячеек, я не знаю, сколько "строк" / строк у меня есть в UICollectionView. Я также не могу определить это количество по количеству элементов в моем источнике данных, так как ячейки, представляющие элементы данных, различаются по ширине, поэтому количество элементов у меня есть в одной строке UICollectionView.
так как я не мог найти никаких намеков на эту тему в официальной документации и googling не принес мне больше, любая помощь и идеи будут оценены очень высоко.
8 ответов:
Эй! По какой-то причине, после нескольких часов исследований, я теперь нашел довольно простой ответ на свой вопрос: я полностью искал в неправильном месте, копаясь во всей документации, которую я мог найти на
UICollectionView.простое и легкое решение заключается в базовом макете: просто позвоните
collectionViewContentSizeнаmyCollectionView.collectionViewLayoutсвойство и вы получаете высоту и ширину содержимого какCGSize. Это так просто.
в случае, если вы используете автоматический макет, то вы можете создать подкласс
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
At
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; }и не забудьте удалить observer:
[self.myCollectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];
user1046037 ответ в Swift...
class DynamicCollectionView: UICollectionView { override func layoutSubviews() { super.layoutSubviews() if bounds.size != intrinsicContentSize() { invalidateIntrinsicContentSize() } } override func intrinsicContentSize() -> CGSize { return self.contentSize } }
Swift 3 Код для ответа user1046037
import UIKit class DynamicCollectionView: UICollectionView { override func layoutSubviews() { super.layoutSubviews() if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) { self.invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { return contentSize } }
слишком поздно отвечать на этот вопрос, но я недавно прошел через эту проблему.
@ли ответ выше поможет мне много, чтобы получить мой ответ. Но этот ответ ограничен С и работал в Свифт.
@lee со ссылкой на ваш ответ, позвольте мне позволить пользователю swift легко решить эту проблему. Для этого, пожалуйста, выполните следующие действия:объявления
CGFloatпеременная в объявлении раздел:var height : CGFloat!At
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") }я надеюсь, что это поможет вам решить вашу проблему быстро.
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 } }
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 } }
Comments