УкрашениеView изменяется, когда AutoSizing ячеек включен в UICollectionViewFlowLayout

Среда:
UICollectionView выглядит как UITableView
Пользовательский подкласс UICollectionViewFlowLayout для определения frame из DecorationView
Включено автоматическое определение размера ячеек

Ожидаемое поведение:
DecorationView, который следует разместить в качестве фона для каждого раздела UICollectionView

Ожидаемое поведение

Наблюдаемое поведение
DecorationView сворачивается до произвольного размера:

Наблюдаемое поведение

Кажется, что UICollectionView пытается вычислить автоматический размер для DecorationView. Если я отключу ячейки Self-Sizing, декоративный вид будет размещен точно в ожидаемом месте.

Есть ли способ отключить автоматическое определение размера для DecorationView?

В моем подклассе UICollectionViewFlowLayout я просто беру первую и последнюю ячейки в разделе и растягиваю фон, чтобы заполнить пространство под ними. Проблема в том, что UICollectionView не учитывает рассчитанный там размер:

override func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
    guard let collectionView = collectionView else {
      return nil
    }

    let section = indexPath.section
    let attrs = UICollectionViewLayoutAttributes(forDecorationViewOfKind: backgroundViewClass.reuseIdentifier(),
                                                 with: indexPath)
    let numberOfItems = collectionView.numberOfItems(inSection: section)
    let lastIndex = numberOfItems - 1

    guard let firstItemAttributes = layoutAttributesForItem(at: IndexPath(indexes: [section, 0])),
      let lastItemAttributes = layoutAttributesForItem(at: IndexPath(indexes: [section, lastIndex])) else {
        return nil
    }

    let startFrame = firstItemAttributes.frame
    let endFrame = lastItemAttributes.frame

    let origin = startFrame.origin
    let size = CGSize(width: startFrame.width,
                      height: -startFrame.minY + endFrame.maxY)

    let frame = CGRect(origin: origin, size: size)
    attrs.frame = frame
    attrs.zIndex = -1

    return attrs
}

person Richard Topchii    schedule 27.02.2018    source источник
comment
Не могли бы вы опубликовать демо на GitHub?   -  person Pranav Kasetti    schedule 01.03.2018


Ответы (2)


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

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

override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) {
    let invalidatedSections = context.invalidatedItemIndexPaths?.map { $0.section } ?? []
    let decorationIndexPaths = invalidatedSections.map { IndexPath(item: 0, section: $0) }
    context.invalidateDecorationElements(ofKind: backgroundViewClass.reuseIdentifier(), at: decorationIndexPaths)
    super.invalidateLayout(with: context)
}
person jamesk    schedule 08.03.2018
comment
Пока я еще не тестировал ваше решение, оно выглядит наиболее многообещающим, я обязательно попробую. Из-за этой проблемы я решил пока не использовать саморегулирующиеся ячейки. - person Richard Topchii; 08.03.2018

Если вы хотите настроить размер по высоте и ширине в flowLayout, вы можете использовать flowLayoutDelegate и установить собственный размер для каждой ячейки в каждом разделе и т. д.

extension YourView: UICollectionViewDelegateFlowLayout {

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

            let widthCell: CGFloat = 30.0
            let heightCell: CGFloat = 50
            let size: CGSize = CGSize(width: widthCell, height: heightCell)
            return size
        }
    }
person Ali ZahediGol    schedule 05.03.2018
comment
Вопрос касается DecorationView, а не UICollectionViewCell.. Этот ответ совершенно не имеет значения, поскольку UICollectionViewDelegateFlowLayout не имеет ни способа запросить размер DecorationView, ни запрашивает его каким-либо другим способом. - person Richard Topchii; 05.03.2018