Подтвердить что ты не робот

UICollectionView автоматически увеличивает высоту

Как правильно изменить размер UICollectionView так, чтобы он полностью отображал его содержимое? Я пробовал много вещей, включая настройку его фрейма, вызов reloadData и недействительность макета:

self.collectionView.contentSize = CGSizeMake(300, 2000);
self.collectionView.frame = CGRectMake(0, 0, 300, 2000);
[self.collectionView reloadData];
[self.collectionView.collectionViewLayout invalidateLayout];

но ничто из этого не имеет никакого эффекта. После нажатия кнопки я все еще вижу начальный вид, например:

collection view only showing part of the content after frame resize

У меня есть небольшая демонстрационная программа, где у меня есть источник данных, производящий 100 элементов. В Interface Builder я первоначально устанавливал размер UICollectionView на небольшое значение, чтобы не все элементы соответствовали, после чего я нажимаю кнопку, после которой выполняется код выше. Я ожидаю, что UICollectionView теперь покажет все элементы, но это не так.

EDIT: Демо-программу можно найти на https://github.com/mjdemilliano/TestUICollectionView.

EDIT2: Я заметил, что обновление кадра в какой-то момент теряется, потому что если я снова нажму кнопку, текущий кадр вернется к старому значению. После добавления некоторых операторов журнала в обработчик событий кнопки вывод журнала:

before: frame = {{0, 58}, {320, 331}}, contentSize = {320, 1190}
update button pressed
after: frame = {{0, 0}, {300, 2000}}, contentSize = {300, 2000}
before: frame = {{0, 58}, {320, 331}}, contentSize = {320, 1190}
update button pressed
after: frame = {{0, 0}, {300, 2000}}, contentSize = {300, 2000}

Я не понимаю, почему изменение кадра не сохраняется, что его меняет.

В какой-то момент я заменю жестко заданные значения на значения, полученные из макета потока, но я хотел бы это исключить и сохранить мой пример как можно более простым.

Контекст: то, что я хочу сделать в конечном итоге, следующее: у меня есть прокручиваемое представление с различными элементами управления, такими как метки и образы, и представление коллекции с динамическим контентом. Я хочу прокрутить все это, а не только просмотр коллекции, поэтому я не использую собственные средства просмотра прокрутки, которые отлично работают.

4b9b3361

Ответ 1

Я решил это в конечном итоге, исправив все ошибки Auto Layout, установив высоту представления коллекции с помощью ограничения. Затем, когда я знаю, что содержимое изменилось, я обновляю значение ограничения, используя значение collectionView.contentSize.height:

self.verticalLayoutConstraint.constant = self.collectionView.contentSize.height;

Затем представление коллекции изменяется правильно, и оно хорошо ведет себя в общем прокрутке. Я обновил тестовый проект GitHub с изменениями.

Для меня, сделав это, обновив ограничение вручную, вместо того, чтобы рассказать iOS: "сделать высоту кадра в представлении коллекции настолько большим, насколько это необходимо" мне не кажется правильным, но это лучшее, что я придумал до сих пор. Пожалуйста, напишите лучший ответ, если он у вас есть.

Ответ 2

Здесь моя реализация в Swift 3:

override func sizeThatFits(_ size: CGSize) -> CGSize {
    if (self.superview != nil) {
        self.superview?.layoutIfNeeded()
    }

    return collectionView.contentSize
}

Ответ 3

UICollectionViewFlowLayout *flowLayout;
flowLayout = [[UICollectionViewFlowLayout alloc]init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
[flowLayout setMinimumInteritemSpacing:0.0f];
[flowLayout setMinimumLineSpacing:0.0f];
[self.collectionView setPagingEnabled:NO];
[flowLayout setItemSize:CGSizeMake(322.0, 148.0)];  //important to leave no white space between the images
[self.collectionView setCollectionViewLayout:flowLayout];

Я обнаружил, что автозапуск в раскадровке не слишком помогает. Правильная настройка для UICollectionViewFlowLayout для вашей коллекцииView - настоящая помощь. Если вы измените размер элемента с помощью setItemSize, вы можете получить желаемый результат.

Ответ 4

Здесь можно связать высоту CollectionView с ее внутренним размером. Я использовал его для правильного размера CollectionView внутри CellView TableView (с динамической высотой ячеек). и он отлично работает.

Сначала добавьте это в подкласс UICollectionView:

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

Затем вызовите layoutIfNeeded() после перезагрузки данных:

reloadData()
layoutIfNeeded()

Ответ 5

Самый простой метод, который я нашел, это переопределить sizeThatFits: методы как есть:

- (CGSize)sizeThatFits:(CGSize)size
{
    if( self.superview )
        [self.superview layoutIfNeeded]; // to force evaluate the real layout

    return self.collectionViewLayout.collectionViewContentSize;
}

Ответ 6

Вы можете попробовать мой пользовательский класс AGCollectionView

  • Назначьте ограничение высоты collectionView, используя раскадровку или программно.

- Назначьте этот класс вашему UICollectionView.

class AGCollectionView: UICollectionView {

    fileprivate var heightConstraint: NSLayoutConstraint!

    override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
        super.init(frame: frame, collectionViewLayout: layout)
        self.associateConstraints()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.associateConstraints()
    }

    override open func layoutSubviews() {
        super.layoutSubviews()

        if self.heightConstraint != nil {
            self.heightConstraint.constant = floor(self.contentSize.height)
        }
        else{
            self.sizeToFit()
            print("Set a heightConstraint set size to fit content")
        }
    }

    func associateConstraints() {
        // iterate through height constraints and identify

        for constraint: NSLayoutConstraint in constraints {
            if constraint.firstAttribute == .height {
                if constraint.relation == .equal {
                    heightConstraint = constraint
                }
            }
        }
    }
}

Ответ 7

Для меня это еще проще, я думаю

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

{
//add following code line after adding cells, before Return
...........
.........
scrollView.contentSize = = collectionView.contentSize;

//now scrollView size is equal to collectionView size. No matter how small or big it is.

return cell;
}