Alex Rivera | Logout

How to make Supplementary View float in UICollectionView as Section Headers do in UITableView plain style

Asked 2012-11-22T11:25:11.653
68

I'm struggling to achieve a "floating section header" effect with UICollectionView. Something that's been easy enough in UITableView (default behavior for UITableViewStylePlain) seems impossible in UICollectionView without lots of hard work. Am I missing the obvious?

Apple provides no documentation on how to achieve this. It seems that one has to subclass UICollectionViewLayout and implement a custom layout just to achieve this effect. This entails quite a bit of work, implementing the following methods:

Methods to Override

Every layout object should implement the following methods:

collectionViewContentSize
layoutAttributesForElementsInRect:
layoutAttributesForItemAtIndexPath:
layoutAttributesForSupplementaryViewOfKind:atIndexPath: (if your layout supports supplementary views)
layoutAttributesForDecorationViewOfKind:atIndexPath: (if your layout supports decoration views)
shouldInvalidateLayoutForBoundsChange:

However its not clear to me how to make the supplementary view float above the cells and "stick" to the top of the view until the next section is reached. Is there a flag for this in the layout attributes?

I would have used UITableView but I need to create a rather complex hierarchy of collections which is easily achieved with a collection view.

Any guidance or sample code would be greatly appreciated!

Edit
Report

1 Answer

47

Either implement the following delegate methods:

– collectionView:layout:sizeForItemAtIndexPath:
– collectionView:layout:insetForSectionAtIndex:
– collectionView:layout:minimumLineSpacingForSectionAtIndex:
– collectionView:layout:minimumInteritemSpacingForSectionAtIndex:
– collectionView:layout:referenceSizeForHeaderInSection:
– collectionView:layout:referenceSizeForFooterInSection:

In your view controller that has your :cellForItemAtIndexPath method (just return the correct values). Or, instead of using the delegate methods, you may also set these values directly in your layout object, e.g. [layout setItemSize:size];.

Using either of these methods will enable you to set your settings in Code rather than IB as they're removed when you set a Custom Layout. Remember to add <UICollectionViewDelegateFlowLayout> to your .h file, too!

Create a new Subclass of UICollectionViewFlowLayout, call it whatever you want, and make sure the H file has:

#import <UIKit/UIKit.h>

@interface YourSubclassNameHere : UICollectionViewFlowLayout

@end

Inside the Implementation File make sure it has the following:

- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {

    NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    UICollectionView * const cv = self.collectionView;
    CGPoint const contentOffset = cv.contentOffset;

    NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet];
    for (UICollectionViewLayoutAttributes *layoutAttributes in answer) {
        if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
            [missingSections addIndex:layoutAttributes.indexPath.section];
        }
    }
    for (UICollectionViewLayoutAttributes *layoutAttributes in answer) {
        if ([layoutAttributes.representedElementKind isEqualTo
answered 2012-12-03T07:27:39.883

Your Answer