6

How do you implement headers in a UICollectionView? I know you can put in supplementary views, but I don't know how to make them "float" above a section like headers in a UITableView do.

Here's my situation: I have a collectionView with the cells laid out in a grid format. You can scroll horizontally and vertically. I want to have a header on top so that when you scroll horizontally it scrolls horizontally with it, but it doesn't scroll vertically. I also want the same sort of thing on the left side where it scrolls vertically with the collectionView but not horizontally. Is implementing this with supplementary views the right approach?

The final functionality I am looking for is similar to that of the Numbers spreadsheet app on iOS.

Thanks in advance for your help!

Faysal Ahmed
  • 6,464
  • 5
  • 23
  • 43
Mason Wolters
  • 464
  • 2
  • 5
  • 13

2 Answers2

21

Update for iOS9:

let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
flow.sectionHeadersPinToVisibleBounds = true

Pass it along.

AMayes
  • 1,767
  • 1
  • 16
  • 29
10

EDIT: As mentioned in the comments, this answer is valid, but not for multiple sections. See this blog for a better solution: http://blog.radi.ws/post/32905838158/sticky-headers-for-uicollectionview-using#notes


You need to specify that behaviour in your layout:

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
  NSMutableArray* attributesArray = [[super layoutAttributesForElementsInRect:rect] mutableCopy];

  BOOL headerVisible = NO;

  for (UICollectionViewLayoutAttributes *attributes in attributesArray) {
    if ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
      headerVisible = YES;
      attributes.frame = CGRectMake(self.collectionView.contentOffset.x, 0, self.headerReferenceSize.width, self.headerReferenceSize.height);
      attributes.alpha = HEADER_ALPHA;
      attributes.zIndex = 2;
    }
  }

  if (!headerVisible) {
    UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                                                                                        atIndexPath:[NSIndexPath
                                                                                                     indexPathForItem:0
                                                                                                     inSection:0]];
    [attributesArray addObject:attributes];
  }

  return attributesArray;
}
Audun Kjelstrup
  • 1,430
  • 8
  • 13
  • So setting the x-origin of the frame to "self.collectionView.contentOffset.x" will make it so it stays attached to the side of the view's frame? Thanks so much for the answer! – Mason Wolters Mar 01 '13 at 15:23
  • In this case, that is correct for the x-axis. For your scenario, you'd need to duplicate with a second header that follows the y-axis. – Audun Kjelstrup Mar 01 '13 at 15:31
  • This is a shabby hack that only works for collection views with headers for only the first section. – Shyam Bhat Dec 26 '13 at 14:00
  • @shyambhat: Thanks for noticing. See this blog for a much better answer than mine: http://blog.radi.ws/post/32905838158/sticky-headers-for-uicollectionview-using#notes – Audun Kjelstrup Dec 27 '13 at 16:01