0
votes

I'm using a horizontally, paging UICollectionView to display a variable number of collection view cells. The size of each collection view cell needs to be equal to that of the collection view and whenever the size of the collection view changes, the size of the collection view cells need to update accordingly. The latter is causing issues. The size of the collection view cells is not updated when the size of the collection view changes.

Invalidating the layout doesn't seem to do the trick. Subclassing UICollectionViewFlowLayout and overriding shouldInvalidateLayoutForBoundsChange: doesn't work either.

For your information, I'm using an instance of UICollectionViewFlowLayout as the collection view's layout object.

3
I have a similar problem. Do you fix it? Thanksdamacri86
@damacri86 I've created a custom collection view by subclassing UIScrollView. This has given me more control over the behavior of the collection view, which is what I needed for this project.Bart Jacobs

3 Answers

2
votes

I think solution below is much cleaner. You only need to override one of UICollectionViewLayout's method like:

- (void)invalidateLayoutWithContext:(UICollectionViewFlowLayoutInvalidationContext *)context
{
  context.invalidateFlowLayoutAttributes = YES;
  context.invalidateFlowLayoutDelegateMetrics = YES;
  [super invalidateLayoutWithContext:context];
}

and

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
  if(!CGSizeEqualToSize(self.collectionView.bounds.size, newBounds.size))
  {
    return YES;
  }

  return NO;
}

as well.

0
votes

I have similar behavior in my app: UICollectionView with cells that should have the same width as collection view at all time. Just returning true from shouldInvalidateLayoutForBoundsChange: didn't work for me either, but I managed to make it work in this way:

class AdaptableFlowLayout: UICollectionViewFlowLayout {
    var previousWidth: CGFloat?

    override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
        let newWidth = newBounds.width
        let shouldIvalidate = newWidth != self.previousWidth
        if shouldIvalidate {
            collectionView?.collectionViewLayout.invalidateLayout()
        }
        self.previousWidth = newWidth
        return false
    }
}

In documentation it is stated that when shouldInvalidateLayoutForBoundsChange returns true then invalidateLayoutWithContext: will be called. I don't know why invalidateLayout works and invalidateLayoutWithContext: doesn't.

0
votes

Swift 4 Xcode 9 implementation for height changes:

final class AdaptableHeightFlowLayout: UICollectionViewFlowLayout {
    var previousHeight: CGFloat?

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        let newHeight = newBounds.height
        let shouldIvalidate = newHeight != self.previousHeight
        if shouldIvalidate {
            collectionView?.collectionViewLayout.invalidateLayout()
        }
        self.previousHeight = newHeight
        return false
    }
}