Skip to content

Commit

Permalink
Merge pull request #11 from foursquare/csmulhern-section-pinning
Browse files Browse the repository at this point in the history
Add ability to have non-pinned headers.

Also adds contentFrameForSection: and other documentation cleanup.

Refactors and resolves conflicts in PR #9
  • Loading branch information
Brian Dorfman committed Apr 13, 2015
2 parents c8643e2 + 793d58b commit 43ca6d6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 24 deletions.
32 changes: 24 additions & 8 deletions FSQCollectionViewAlignedLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,22 @@
*/
@property (nonatomic) UIEdgeInsets contentInsets;

/**
Determines if the current section's header is pinned to the top of the collection view.
Defaults to YES.
@note This is similar to the behavior observed in UITableView's with the style UITableViewStylePlain.
*/
@property (nonatomic) BOOL shouldPinSectionHeadersToTop;

/**
@param section The section of the collection view.
@return The frame for the section, or CGRectZero if the section is out of range.
*/
- (CGRect)contentFrameForSection:(NSInteger)section;

@end


Expand All @@ -106,14 +122,14 @@
remainingLineSpace:(CGFloat)remainingLineSpace;

/**
* Asks the delegate for the height of the header view in the specified section.
* If you do not implement this method, or the height returned is 0, no header is added.
*
* @param collectionView The collection view object displaying the layout.
* @param collectionViewLayout The layout object requesting the information.
* @param section The index of the section whose header size is being requested.
*
* @return The height of the header. If you return a value of 0, no header is added.
Asks the delegate for the height of the header view in the specified section.
If you do not implement this method, or the height returned is 0, no header is added.
@param collectionView The collection view object displaying the layout.
@param collectionViewLayout The layout object requesting the information.
@param section The index of the section whose header size is being requested.
@return The height of the header. If you return a value of 0, no header is added.
*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceHeightForHeaderInSection:(NSInteger)section;

Expand Down
41 changes: 25 additions & 16 deletions FSQCollectionViewAlignedLayout.m
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ - (void)setupDefaults {
self.totalContentSize = CGSizeZero;
self.sectionSpacing = 10.f;
self.contentInsets = UIEdgeInsetsMake(5., 5., 5., 5.);
self.shouldPinSectionHeadersToTop = YES;
}

#pragma mark - Layout calculation -
Expand Down Expand Up @@ -568,22 +569,24 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind
if (sectionData.headerAttributes) {
attributes = [sectionData.headerAttributes copy];

NSInteger section = indexPath.section;
NSInteger numberOfItemsInSection = [self.collectionView numberOfItemsInSection:section];

NSIndexPath *firstCellIndexPath = [NSIndexPath indexPathForItem:0 inSection:section];
NSIndexPath *lastCellIndexPath = [NSIndexPath indexPathForItem:MAX(0, (numberOfItemsInSection - 1)) inSection:section];

UICollectionViewLayoutAttributes *firstCellAttributes = [self layoutAttributesForItemAtIndexPath:firstCellIndexPath];
UICollectionViewLayoutAttributes *lastCellAttributes = [self layoutAttributesForItemAtIndexPath:lastCellIndexPath];

if (firstCellAttributes && lastCellAttributes) {
CGFloat headerHeight = attributes.frame.size.height;
CGFloat minY = CGRectGetMinY(sectionData.sectionRect);
CGFloat maxY = CGRectGetMaxY(sectionData.sectionRect) - headerHeight;
CGFloat yOffset = MIN(MAX(self.collectionView.contentOffset.y + self.collectionView.contentInset.top, minY), maxY);
attributes.frame = CGRectMake(0.0f, yOffset, self.collectionViewContentSize.width, headerHeight);
attributes.zIndex = NSIntegerMax;
if (self.shouldPinSectionHeadersToTop) {
NSInteger section = indexPath.section;
NSInteger numberOfItemsInSection = [self.collectionView numberOfItemsInSection:section];

NSIndexPath *firstCellIndexPath = [NSIndexPath indexPathForItem:0 inSection:section];
NSIndexPath *lastCellIndexPath = [NSIndexPath indexPathForItem:MAX(0, (numberOfItemsInSection - 1)) inSection:section];

UICollectionViewLayoutAttributes *firstCellAttributes = [self layoutAttributesForItemAtIndexPath:firstCellIndexPath];
UICollectionViewLayoutAttributes *lastCellAttributes = [self layoutAttributesForItemAtIndexPath:lastCellIndexPath];

if (firstCellAttributes && lastCellAttributes) {
CGFloat headerHeight = attributes.frame.size.height;
CGFloat minY = CGRectGetMinY(sectionData.sectionRect);
CGFloat maxY = CGRectGetMaxY(sectionData.sectionRect) - headerHeight;
CGFloat yOffset = MIN(MAX(self.collectionView.contentOffset.y + self.collectionView.contentInset.top, minY), maxY);
attributes.frame = CGRectMake(0.0f, yOffset, self.collectionViewContentSize.width, headerHeight);
attributes.zIndex = NSIntegerMax;
}
}
}
}
Expand Down Expand Up @@ -673,6 +676,12 @@ - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state object
return [self.sectionsData countByEnumeratingWithState:state objects:buffer count:len];
}

#pragma mark - Layout information helpers -

- (CGRect)contentFrameForSection:(NSInteger)section {
return (section < self.sectionsData.count) ? [self.sectionsData[section] sectionRect] : CGRectZero;
}

@end

@implementation FSQCollectionViewAlignedLayoutSectionAttributes
Expand Down

0 comments on commit 43ca6d6

Please sign in to comment.