Question

i'm having problems to align the first row to the top when I have different UICollectionViewCell heights and I don't know why. It seems that minimumLineSpacingForSectionAtIndex method is not working.

Here is my result:

enter image description here

As you can see, the first row is not aligned to the top.

This is my code:

- (void)viewDidLoad
{
...
FlowLayout *flowLayout = [[FlowLayout alloc] init];
flowLayout.itemSize = CGSizeMake(152, 260);
flowLayout.sectionInset = UIEdgeInsetsMake( 5, 5, 5, 5);
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
self.collectionView.collectionViewLayout = flowLayout;
...
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:
(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)
indexPath{

if (indexPath.row == 0)
    return CGSizeMake(152, 200);
if (indexPath.row == 1)
    return CGSizeMake(152, 270);

return CGSizeMake(152, 300);
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:
(UICollectionViewLayout*)collectionViewLayout    
minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {

return 5.0;

}

- (CGFloat)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout*)collectionViewLayout 
minimumLineSpacingForSectionAtIndex:(NSInteger)section {

return 8.0;

}

This is the code of my FlowLayout:

@implementation FlowLayout

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 
{
NSMutableArray *result = [NSMutableArray array];
NSInteger sectionCount = 1;
if ([self.collectionView.dataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)])
{
    sectionCount = [self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView];
}
for (int s = 0; s < sectionCount; s++)
{
    NSInteger itemCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:s];
    for (int i = 0; i < itemCount; i++)
    {
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:s];
        UICollectionViewLayoutAttributes *layoutAttributes = 
        [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
        if (layoutAttributes != nil) {
            [result addObject:layoutAttributes];
        }
        UICollectionViewLayoutAttributes *layout = [self layoutAttributesForItemAtIndexPath:indexPath];
        if (CGRectIntersectsRect(rect, layout.frame))
        {
            [result addObject:layout];
        }
    }
}
return result;
}


- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* atts =
[super layoutAttributesForItemAtIndexPath:indexPath];

if (indexPath.item == 0 || indexPath.item == 1) // degenerate case 1, first item of section
    return atts;

NSIndexPath* ipPrev =
[NSIndexPath indexPathForItem:indexPath.item-2 inSection:indexPath.section];

CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
CGFloat rightPrev = fPrev.origin.y + fPrev.size.height + 10;
if (atts.frame.origin.y <= rightPrev) // degenerate case 2, first item of line
    return atts;

CGRect f = atts.frame;
f.origin.y = rightPrev;
atts.frame = f;
return atts; 
}

- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
return YES;
}
Was it helpful?

Solution

What you are experiencing is a normal cell placement when using the UICollectionViewFlowLayout.

You have to tweak the layout attributes being returned by the flow layout. To do so, override the layoutAttributesForElementsInRect: method and any of the methods that return layout attributes. Modify the attributes provided by the parent class, and then return them. The attribute you have to modify is frame.

A good example of doing it is a sample code from Apple - Custom Layouts: A Worked Example

Update after attaching implementation of the layout.

Looks like in the layoutAttributesForItemAtIndexPath: method you are not adjusting the frame for first item (index 0). You are returning the attributes you get from parent class. Change the frame's origin.y to 0 for item 0.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top