2

I have a vertically scrolling collection view with flow layout. I have subclassed the layout object in order to align the elements to the left on each line (with code borrowed from here and there), and place the section headers on the left margin (inset) of each section (instead of above), but otherwise it's just a flow layout.

I want to force the cells for some items (not all) to be placed "on the next line", even if there is room to fit them to the right of the previously placed cell.

The only place where I can see myself doing this is when overriding the UICollectionViewFlowLayout method layoutAttributesForItemAtIndexPath(_:).

However, only the delegate/data source knows which items require a new line, and none of the methods from UICollectionViewDelegate, UICollectionViewDataSource or UICollectionViewDelegateFlowLayout seem to give me a chance to specify that.

What would be an elegant way of achieving this?

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189

1 Answers1

2

You are right, UICollectionViewFlowLayout is made for positioning items in your collectionView.

You can use both layoutAttributesForItemAtIndexPath and layoutAttributesForElementsInRect combined to set items positions as explained here : https://stackoverflow.com/a/25566843/4320246

In your case, you have several solutions to determine the positions of each item in your collectionView :

  1. Define the absolute position of each item and supplementary view in the collectionView in your subclass of UICollectionViewFlowLayout
  2. Let your subclass of UICollectionViewFlowLayout decide if an item requires a new line and change its UICollectionViewLayoutAttributes
  3. Create a new protocol subclassing UICollectionViewDelegateFlowLayout and add a method like - (BOOL)shouldItemBePlacedOnTheNextLineAtIndexPath: and call this method in your subclass of UICollectionViewFlowLayout like this :

    BOOL shouldPlaceOnNextLine = NO;

    id < MySubProtocolOfUICollectionViewDelegate > flowLayoutDelegate = (id < MySubProtocolOfUICollectionViewDelegate >)self.collectionView.delegate;
    if ([flowLayoutDelegate respondsToSelector:@selector(shouldItemBePlacedOnTheNextLineAtIndexPath:)]) {
        shouldPlaceOnNextLine = [flowLayoutDelegate shouldItemBePlacedOnTheNextLineAtIndexPath:indexPath]
    }
    

However, I suggest you to adopt the first solution : let your subclass of UICollectionViewFlowLayout determine the positions of items and supplementary views, and in your dataSource/delegate call [(MyCustomFlowLayout *)self.collectionView.collectionViewLayout isItemForceOnNewLine] if you need it.

In my mind, it is the most elegant solution because you can still switch from one custom layout to an other if you want to dynamically change the collectionView appearance.

Community
  • 1
  • 1
vmeyer
  • 1,998
  • 21
  • 23