From 5d9b7a7b2bc811319b54fd1e1bf7623f28233da4 Mon Sep 17 00:00:00 2001 From: Cameron Mulhern Date: Mon, 13 Apr 2015 17:23:38 -0400 Subject: [PATCH 1/3] Merge branch 'master' of https://github.com/calendreco/FSQCollectionViewAlignedLayout --- FSQCollectionViewAlignedLayout.h | 14 +++++++++++ FSQCollectionViewAlignedLayout.m | 41 +++++++++++++++++++------------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/FSQCollectionViewAlignedLayout.h b/FSQCollectionViewAlignedLayout.h index f0a7822..cea7f07 100644 --- a/FSQCollectionViewAlignedLayout.h +++ b/FSQCollectionViewAlignedLayout.h @@ -80,6 +80,20 @@ */ @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; + +/** + Returns the frame for the section indentified by sectionIdx, or CGRectZero if sectionIdx is out of range. + */ +- (CGRect)contentFrameForSection:(NSInteger)section; + @end diff --git a/FSQCollectionViewAlignedLayout.m b/FSQCollectionViewAlignedLayout.m index c1f1637..4825a81 100644 --- a/FSQCollectionViewAlignedLayout.m +++ b/FSQCollectionViewAlignedLayout.m @@ -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 - @@ -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; + } } } } @@ -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 [self.sectionsData[section] sectionRect]; +} + @end @implementation FSQCollectionViewAlignedLayoutSectionAttributes From b408eded1dce35c95ecd2014e593a2f1bf7fe4e5 Mon Sep 17 00:00:00 2001 From: Cameron Mulhern Date: Mon, 13 Apr 2015 17:36:30 -0400 Subject: [PATCH 2/3] Adds bounds checking to contentFrameForSection --- FSQCollectionViewAlignedLayout.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FSQCollectionViewAlignedLayout.m b/FSQCollectionViewAlignedLayout.m index 4825a81..2f28a69 100644 --- a/FSQCollectionViewAlignedLayout.m +++ b/FSQCollectionViewAlignedLayout.m @@ -679,7 +679,7 @@ - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state object #pragma mark - Layout information helpers - - (CGRect)contentFrameForSection:(NSInteger)section { - return [self.sectionsData[section] sectionRect]; + return (section < self.sectionsData.count) ? [self.sectionsData[section] sectionRect] : CGRectZero; } @end From 793d58bb4112b7b39bc1860a687a58bf4d9b9a6b Mon Sep 17 00:00:00 2001 From: Cameron Mulhern Date: Mon, 13 Apr 2015 17:36:39 -0400 Subject: [PATCH 3/3] Fixes documentation styling --- FSQCollectionViewAlignedLayout.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/FSQCollectionViewAlignedLayout.h b/FSQCollectionViewAlignedLayout.h index cea7f07..1fa3e47 100644 --- a/FSQCollectionViewAlignedLayout.h +++ b/FSQCollectionViewAlignedLayout.h @@ -90,7 +90,9 @@ @property (nonatomic) BOOL shouldPinSectionHeadersToTop; /** - Returns the frame for the section indentified by sectionIdx, or CGRectZero if sectionIdx is out of range. + @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; @@ -120,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;