DecorationView получает изменение размера, если в UICollectionViewFlowLayout включено автоматическое изменение размера ячеек

среда:
UICollectionView это похоже на UITableView
Пользовательский подкласс UICollectionViewFlowLayout для определения frame на DecorationView
Self-Sizing ячейки включены

ожидаемое поведение:
А DecorationView это должно быть помещено в качестве фона для каждого раздела UICollectionView

Expected Behavior

Наблюдаемое Поведение:
The DecorationView рухнет до произвольного размера:

Observed Behavior

кажется, что 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
}

2 ответов


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

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

override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) {
    let invalidatedSections = context.invalidatedItemIndexPaths?.map { .section } ?? []
    let decorationIndexPaths = invalidatedSections.map { IndexPath(item: 0, section: ) }
    context.invalidateDecorationElements(ofKind: backgroundViewClass.reuseIdentifier(), at: decorationIndexPaths)
    super.invalidateLayout(with: context)
}

Если вы хотите пользовательский размер для высоты и ширины в 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
        }
    }