Ячейки представления коллекции непреднамеренно изменяют размер при прокрутке до нижней части CollectionView. - PullRequest
0 голосов
/ 07 ноября 2019

Я создаю коллекционный вид (галерею) изображений.

Макет состоит из 3 ячеек на строку.

 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        let width: CGFloat = (view.frame.width / 3) - 8
        let height: CGFloat = width

        return CGSize(width: width, height: height)
    }

Все выглядит отлично, пока я не прокручиваю до конца представления коллекции.

он идет от: 3 на строку, хорошо выглядит

до: супер взорванная картинка, больше экрана

Я также получаю это сообщение об ошибке:

The behavior of the UICollectionViewFlowLayout is not defined because:

the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values. 

Please check the values returned by the delegate.

The relevant UICollectionViewFlowLayout instance is <UICollectionViewFlowLayout: 0x7fa97f708c70>, and it is attached to <UICollectionView: 0x7fa981022000; frame = (0 0; 414 896); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x6000019986f0>; layer = <CALayer: 0x6000017a8820>; contentOffset: {0, 498.33333333333331}; contentSize: {414, 1250}; adjustedContentInset: {88, 0, 34, 0}; layout: <UICollectionViewFlowLayout: 0x7fa97f708c70>; dataSource: <MarsRover.GalleryCollectionVC: 0x7fa97f50b610>>.

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

Ответы [ 3 ]

0 голосов
/ 08 ноября 2019

Ошибка, которую вы получаете, указывает на ширину элемента, так как проблема, по сути, говорит о том, что ширина и интервал между элементами не могут превышать ширину представления коллекции. Это связано с тем, что представление вашей коллекции имеет вертикальную прокрутку.

Таким образом, чтобы обеспечить правильное поведение для представления коллекции, вы должны установить контроллер как delegate для представления коллекции и также принять UICollectionViewDelegateFlowLayout. В вашем случае я вижу, что вы уже реализовали метод collectionView(_:, layout:, sizeForItemAt:.

В вашей реализации есть явное намерение разделить ширину collectionView на три равные части. В расчете учитывается третья часть из self.view.width минус восемь. Если я правильно предполагаю, что вы намерены оставить интервал между элементами 8. Если это так, вы должны указать его в другом методе:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 8
}

Это будет указывать интервал между элементами до 8 баллов.

Продолжая с width и height ячейки, вы должны затем разделить collectionView.frame.width , но перед этим вы должны вычесть промежуточное значение из этой величины , потому что этоэто оставшееся пространство для ваших ячеек.

Таким образом, ваша реализация будет

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    // We subtract 16 because there are 2 inter item spaces like:
    // [CELL] [spacing:8] [CELL] [spacing:8] [CELL]
    let usableWidth = collectionView.frame.width - (2 * 8) 

    let cellWidth: CGFloat = usableWidth / 3
    let cellHeight: CGFloat = cellWidth

    return CGSize(width: cellWidth, height: cellHeight)
}

Это должно сделать макет для вас.

0 голосов
/ 08 ноября 2019

Прежде всего, почему бы не использовать bounds вместо frame ?

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

Используете ли вы методы UIScrollViewDelegate, чтобы что-то делать с макетом?

0 голосов
/ 08 ноября 2019

Поскольку все ваши элементы имеют одинаковый размер, вы не должны устанавливать их в методе делегата. Вместо этого установите статический размер для вашего flowLayout (вы можете перетащить выход из раскадровки) в viewDidLayoutSubviews и используйте для этого вставки макета, чтобы вы не могли неправильно понять математику:

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let remainingSpace = collectionView.bounds.width
                            - flowLayout.sectionInset.left
                            - flowLayout.sectionInset.right
                            - flowLayout.minimumInteritemSpacing * (Constant.numberOfItemsAcross - 1)
        let dimension = remainingSpace / Constant.numberOfItemsAcross
        flowLayout.itemSize = CGSize(width: dimension, height: dimension)
    }
...