DecorationView gets size when AutoSize cells are included in UICollectionViewFlowLayout

Environment:
UICollectionView that looks like a UITableView
Custom subclass of UICollectionViewFlowLayout to define frame DecorationView
Self-sized cells are included.

Expected Behavior:
A DecorationView that should be placed as the background for each section of the UICollectionView

Expected Behavior

Observed Behavior:
DecorationView collapses to an arbitrary size:

Observed behavior

It seems that UICollectionView trying to calculate the automatic size for DecorationView . If I turn off Self-Sizing cells, the decoration view will be placed exactly in the expected location.

Is it possible to disable self-esteem for DecorationView ?

In my subclass of UICollectionViewFlowLayout I just take the first and last cells in the section and stretch the background to fill the space under them. The problem is that the UICollectionView does not take into account the size calculated there:

 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 } 
+7
ios autolayout swift uicollectionview
source share
2 answers

It is possible that the frames of your jewelry are not updated (i.e. invalid) after the frames of your cells were self-sized. As a result, the width of each decorative view remains the default.

Try this function, which should invalidate the decoration presentation layout for each section each time the layout of an element in this section is invalid:

 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) } 
+1
source share

If you want a custom size for the height and width in flowLayout, you can use flowLayoutDelegate and set your own size for each cell in each section, etc.

 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 } } 
+2
source share

All Articles