From 90ad002e04f4122f86b98e11575050b63f1604e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Virin?= Date: Fri, 14 Feb 2014 15:50:15 +0100 Subject: [PATCH 1/6] switch back to Flow layout --- NHBalancedFlowLayout/NHBalancedFlowLayout.h | 22 +------------ NHBalancedFlowLayout/NHBalancedFlowLayout.m | 35 --------------------- 2 files changed, 1 insertion(+), 56 deletions(-) diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.h b/NHBalancedFlowLayout/NHBalancedFlowLayout.h index 7d51164..8c5d3d5 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.h +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.h @@ -16,31 +16,11 @@ * Currently this class does not support supplementary or decoration views. * */ -@interface NHBalancedFlowLayout : UICollectionViewLayout +@interface NHBalancedFlowLayout : UICollectionViewFlowLayout // The preferred size for each row measured in the scroll direction @property (nonatomic) CGFloat preferredRowSize; -// The size of each section's header. This maybe dynamically adjusted -// per section via the protocol method referenceSizeForHeaderInSection. -@property (nonatomic) CGSize headerReferenceSize; - -// The size of each section's header. This maybe dynamically adjusted -// per section via the protocol method referenceSizeForFooterInSection. -@property (nonatomic) CGSize footerReferenceSize; - -// The margins used to lay out content in a section. -@property (nonatomic) UIEdgeInsets sectionInset; - -// The minimum spacing to use between lines of items in the grid. -@property (nonatomic) CGFloat minimumLineSpacing; - -// The minimum spacing to use between items in the same row. -@property (nonatomic) CGFloat minimumInteritemSpacing; - -// The scroll direction of the grid. -@property (nonatomic) UICollectionViewScrollDirection scrollDirection; - @end diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.m b/NHBalancedFlowLayout/NHBalancedFlowLayout.m index 4df7fde..961508a 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.m +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.m @@ -389,41 +389,6 @@ - (void)setPreferredRowSize:(CGFloat)preferredRowHeight [self invalidateLayout]; } -- (void)setSectionInset:(UIEdgeInsets)sectionInset -{ - _sectionInset = sectionInset; - - [self invalidateLayout]; -} - -- (void)setMinimumLineSpacing:(CGFloat)minimumLineSpacing -{ - _minimumLineSpacing = minimumLineSpacing; - - [self invalidateLayout]; -} - -- (void)setMinimumInteritemSpacing:(CGFloat)minimumInteritemSpacing -{ - _minimumInteritemSpacing = minimumInteritemSpacing; - - [self invalidateLayout]; -} - -- (void)setHeaderReferenceSize:(CGSize)headerReferenceSize -{ - _headerReferenceSize = headerReferenceSize; - - [self invalidateLayout]; -} - -- (void)setFooterReferenceSize:(CGSize)footerReferenceSize -{ - _footerReferenceSize = footerReferenceSize; - - [self invalidateLayout]; -} - #pragma mark - Delegate - (id)delegate From b2950adba686d9a1adece9ff821a725312eb4af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Virin?= Date: Tue, 18 Feb 2014 17:01:22 +0100 Subject: [PATCH 2/6] sticky headers --- NHBalancedFlowLayout/NHBalancedFlowLayout.h | 3 + NHBalancedFlowLayout/NHBalancedFlowLayout.m | 58 ++++++++++++++++++- .../NHBalancedFlowLayoutDemo/ViewController.m | 3 +- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.h b/NHBalancedFlowLayout/NHBalancedFlowLayout.h index 8c5d3d5..18ad578 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.h +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.h @@ -21,6 +21,9 @@ // The preferred size for each row measured in the scroll direction @property (nonatomic) CGFloat preferredRowSize; +// Use this to stick the headers to the origin. +@property (nonatomic, assign) BOOL stickyHeaders; + @end diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.m b/NHBalancedFlowLayout/NHBalancedFlowLayout.m index 961508a..c45d8f4 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.m +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.m @@ -68,7 +68,7 @@ - (void)initialize { // set to NULL so it is not released by accident in dealloc _itemFrameSections = NULL; - + self.stickyHeaders = NO; self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); self.minimumLineSpacing = 10; self.minimumInteritemSpacing = 10; @@ -194,6 +194,32 @@ - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect } } + if (self.stickyHeaders) + { + NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet]; + for (NSUInteger idx = 0; idx < [layoutAttributes count]; idx++) + { + UICollectionViewLayoutAttributes *layoutAttribute = layoutAttributes[idx]; + + if (layoutAttribute.representedElementCategory == UICollectionElementCategoryCell) { + [missingSections addIndex:layoutAttribute.indexPath.section]; // remember that we need to layout header for this section + } + if ([layoutAttribute.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) { + [layoutAttributes removeObjectAtIndex:idx]; // remove layout of header done by our super, we will do it right later + idx--; + } + } + + // layout all headers needed for the rect using self code + [missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx]; + UICollectionViewLayoutAttributes *layoutAttribute = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; + [layoutAttributes addObject:layoutAttribute]; + }]; + } + + return layoutAttributes; } @@ -221,11 +247,41 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind attributes = nil; } + if (self.stickyHeaders && attributes && [kind isEqualToString:UICollectionElementKindSectionHeader]) + { + UIEdgeInsets const contentEdgeInsets = self.collectionView.contentInset; + CGPoint const contentOffset = CGPointMake(self.collectionView.contentOffset.x, + self.collectionView.contentOffset.y + contentEdgeInsets.top); + + CGPoint nextHeaderOrigin = CGPointMake(INFINITY, INFINITY); + + if (indexPath.section + 1 < [self.collectionView numberOfSections]) + { + UICollectionViewLayoutAttributes *nextHeaderAttributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section+1]]; + nextHeaderOrigin = nextHeaderAttributes.frame.origin; + } + + CGRect frame = attributes.frame; + if (self.scrollDirection == UICollectionViewScrollDirectionVertical) { + frame.origin.y = MIN(MAX(contentOffset.y, frame.origin.y), nextHeaderOrigin.y - CGRectGetHeight(frame)); + } + else { // UICollectionViewScrollDirectionHorizontal + frame.origin.x = MIN(MAX(contentOffset.x, frame.origin.x), nextHeaderOrigin.x - CGRectGetWidth(frame)); + } + attributes.zIndex = NSIntegerMax; + attributes.frame = frame; + + + } + return attributes; } - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { + return YES; + + // TODO: dirty ! CGRect oldBounds = self.collectionView.bounds; if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds) || CGRectGetHeight(newBounds) != CGRectGetHeight(oldBounds)) { return YES; diff --git a/NHBalancedFlowLayoutDemo/NHBalancedFlowLayoutDemo/ViewController.m b/NHBalancedFlowLayoutDemo/NHBalancedFlowLayoutDemo/ViewController.m index 69fcddc..f29f640 100644 --- a/NHBalancedFlowLayoutDemo/NHBalancedFlowLayoutDemo/ViewController.m +++ b/NHBalancedFlowLayoutDemo/NHBalancedFlowLayoutDemo/ViewController.m @@ -46,6 +46,7 @@ - (void)viewDidLoad [super viewDidLoad]; NHBalancedFlowLayout *layout = (NHBalancedFlowLayout *)self.collectionViewLayout; + layout.stickyHeaders = YES; layout.headerReferenceSize = CGSizeMake(HEADER_SIZE, HEADER_SIZE); layout.footerReferenceSize = CGSizeMake(FOOTER_SIZE, FOOTER_SIZE); } @@ -61,7 +62,7 @@ - (CGSize)collectionView:(UICollectionView *)collectionView layout:(NHBalancedFl - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { - return 1; + return 3; } - (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section; From def49b317b0c3ddefca277612160bd1eed9cec78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Virin?= Date: Tue, 18 Feb 2014 17:15:42 +0100 Subject: [PATCH 3/6] clean --- NHBalancedFlowLayout/NHBalancedFlowLayout.m | 8 -------- 1 file changed, 8 deletions(-) diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.m b/NHBalancedFlowLayout/NHBalancedFlowLayout.m index c45d8f4..a40459d 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.m +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.m @@ -280,14 +280,6 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { return YES; - - // TODO: dirty ! - CGRect oldBounds = self.collectionView.bounds; - if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds) || CGRectGetHeight(newBounds) != CGRectGetHeight(oldBounds)) { - return YES; - } - - return NO; } #pragma mark - Layout helpers From 44d4509cf3a7faacc42acc383a724f8f6f286adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Virin?= Date: Tue, 18 Feb 2014 17:44:38 +0100 Subject: [PATCH 4/6] sticky headers --- NHBalancedFlowLayout/NHBalancedFlowLayout.h | 22 +++++++++- NHBalancedFlowLayout/NHBalancedFlowLayout.m | 45 ++++++++++++++++----- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.h b/NHBalancedFlowLayout/NHBalancedFlowLayout.h index 18ad578..c299f1d 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.h +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.h @@ -16,7 +16,7 @@ * Currently this class does not support supplementary or decoration views. * */ -@interface NHBalancedFlowLayout : UICollectionViewFlowLayout +@interface NHBalancedFlowLayout : UICollectionViewLayout // The preferred size for each row measured in the scroll direction @property (nonatomic) CGFloat preferredRowSize; @@ -24,6 +24,26 @@ // Use this to stick the headers to the origin. @property (nonatomic, assign) BOOL stickyHeaders; +// The size of each section's header. This maybe dynamically adjusted +// per section via the protocol method referenceSizeForHeaderInSection. +@property (nonatomic) CGSize headerReferenceSize; + +// The size of each section's header. This maybe dynamically adjusted +// per section via the protocol method referenceSizeForFooterInSection. +@property (nonatomic) CGSize footerReferenceSize; + +// The margins used to lay out content in a section. +@property (nonatomic) UIEdgeInsets sectionInset; + +// The minimum spacing to use between lines of items in the grid. +@property (nonatomic) CGFloat minimumLineSpacing; + +// The minimum spacing to use between items in the same row. +@property (nonatomic) CGFloat minimumInteritemSpacing; + +// The scroll direction of the grid. +@property (nonatomic) UICollectionViewScrollDirection scrollDirection; + @end diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.m b/NHBalancedFlowLayout/NHBalancedFlowLayout.m index c45d8f4..190924c 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.m +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.m @@ -257,7 +257,7 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind if (indexPath.section + 1 < [self.collectionView numberOfSections]) { - UICollectionViewLayoutAttributes *nextHeaderAttributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section+1]]; + UICollectionViewLayoutAttributes *nextHeaderAttributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section+1]]; nextHeaderOrigin = nextHeaderAttributes.frame.origin; } @@ -280,14 +280,6 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { return YES; - - // TODO: dirty ! - CGRect oldBounds = self.collectionView.bounds; - if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds) || CGRectGetHeight(newBounds) != CGRectGetHeight(oldBounds)) { - return YES; - } - - return NO; } #pragma mark - Layout helpers @@ -445,6 +437,41 @@ - (void)setPreferredRowSize:(CGFloat)preferredRowHeight [self invalidateLayout]; } +- (void)setSectionInset:(UIEdgeInsets)sectionInset +{ + _sectionInset = sectionInset; + + [self invalidateLayout]; +} + +- (void)setMinimumLineSpacing:(CGFloat)minimumLineSpacing +{ + _minimumLineSpacing = minimumLineSpacing; + + [self invalidateLayout]; +} + +- (void)setMinimumInteritemSpacing:(CGFloat)minimumInteritemSpacing +{ + _minimumInteritemSpacing = minimumInteritemSpacing; + + [self invalidateLayout]; +} + +- (void)setHeaderReferenceSize:(CGSize)headerReferenceSize +{ + _headerReferenceSize = headerReferenceSize; + + [self invalidateLayout]; +} + +- (void)setFooterReferenceSize:(CGSize)footerReferenceSize +{ + _footerReferenceSize = footerReferenceSize; + + [self invalidateLayout]; +} + #pragma mark - Delegate - (id)delegate From d2b0e116a3f88ca8694b64eba74f833e235638c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Virin?= Date: Tue, 18 Feb 2014 18:26:31 +0100 Subject: [PATCH 5/6] fix bug --- NHBalancedFlowLayout/NHBalancedFlowLayout.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.m b/NHBalancedFlowLayout/NHBalancedFlowLayout.m index a40459d..65f1e40 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.m +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.m @@ -257,7 +257,7 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind if (indexPath.section + 1 < [self.collectionView numberOfSections]) { - UICollectionViewLayoutAttributes *nextHeaderAttributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section+1]]; + UICollectionViewLayoutAttributes *nextHeaderAttributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section+1]]; nextHeaderOrigin = nextHeaderAttributes.frame.origin; } From d90a2c65f6ad3226046846795446b9b985a5b398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Virin?= Date: Wed, 19 Feb 2014 11:06:53 +0100 Subject: [PATCH 6/6] improvments --- NHBalancedFlowLayout/NHBalancedFlowLayout.m | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/NHBalancedFlowLayout/NHBalancedFlowLayout.m b/NHBalancedFlowLayout/NHBalancedFlowLayout.m index 65f1e40..07b6d50 100644 --- a/NHBalancedFlowLayout/NHBalancedFlowLayout.m +++ b/NHBalancedFlowLayout/NHBalancedFlowLayout.m @@ -279,7 +279,17 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { - return YES; + BOOL shouldInvalidateLayout = NO; + CGRect oldBounds = self.collectionView.bounds; + if (self.stickyHeaders) + { + shouldInvalidateLayout = YES; + } + else if (CGRectGetWidth(newBounds) != CGRectGetWidth(oldBounds) || CGRectGetHeight(newBounds) != CGRectGetHeight(oldBounds)) { + shouldInvalidateLayout = YES; + } + + return shouldInvalidateLayout; } #pragma mark - Layout helpers