Skip to content

Commit

Permalink
Merge pull request #5 from foursquare/section-headers
Browse files Browse the repository at this point in the history
Adds support for pinned section headers
  • Loading branch information
Brian Dorfman committed Jan 21, 2015
2 parents 94e3033 + 3749c36 commit b7ea95d
Show file tree
Hide file tree
Showing 4 changed files with 380 additions and 220 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

@interface FSQExampleSectionData : NSObject
@property (nonatomic) FSQCollectionViewHorizontalAlignment hAlignment;
@property (nonatomic) NSString *headerString;
@property (nonatomic) NSArray *cellData;
@end

Expand All @@ -27,6 +28,28 @@ @interface FSQExampleCellData : NSObject
@implementation FSQExampleCellData
@end

@interface FSQExampleHeaderView : UICollectionReusableView
@property (nonatomic) UILabel *label;
@end

@implementation FSQExampleHeaderView

- (instancetype)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
self.backgroundColor = [UIColor colorWithWhite:0.96f alpha:1.0f];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(15.0f, 0, frame.size.width - 30.0f, frame.size.height)];
label.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
label.backgroundColor = [UIColor clearColor];
label.font = kMainFont;
label.numberOfLines = 1;
[self addSubview:label];
self.label = label;
}
return self;
}

@end

@interface FSQExampleCell : UICollectionViewCell
@property (nonatomic) UILabel *label;
@end
Expand Down Expand Up @@ -72,7 +95,9 @@ - (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.collectionView.backgroundColor = [UIColor whiteColor];
self.collectionView.alwaysBounceVertical = YES;
[self.collectionView registerClass:[FSQExampleCell class] forCellWithReuseIdentifier:@"cell"];
[self.collectionView registerClass:[FSQExampleHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];

CGRect frame = self.collectionView.frame;
frame.origin.y += 20;
Expand Down Expand Up @@ -136,6 +161,22 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
return cell;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceHeightForHeaderInSection:(NSInteger)section {
FSQExampleSectionData *sectionData = self.sectionData[section];
return (sectionData.headerString.length > 0) ? 30.0f : 0.0f;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
UICollectionReusableView *view = nil;
if (kind == UICollectionElementKindSectionHeader) {
FSQExampleSectionData *sectionData = self.sectionData[indexPath.section];
FSQExampleHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"header" forIndexPath:indexPath];
headerView.label.text = sectionData.headerString;
view = headerView;
}
return view;
}

- (NSArray *)generateExampleData {
// First section
FSQExampleSectionData *sectionOne = [FSQExampleSectionData new];
Expand All @@ -148,6 +189,7 @@ - (NSArray *)generateExampleData {
// Second section
FSQExampleSectionData *sectionTwo = [FSQExampleSectionData new];
sectionTwo.hAlignment = FSQCollectionViewHorizontalAlignmentLeft;
sectionTwo.headerString = @"Paul";

FSQExampleCellData *sectionTwoAvatarCell = [FSQExampleCellData new];
sectionTwoAvatarCell.backgroundColor = [UIColor redColor];
Expand All @@ -170,6 +212,7 @@ - (NSArray *)generateExampleData {
// Third Section
FSQExampleSectionData *sectionThree = [FSQExampleSectionData new];
sectionThree.hAlignment = FSQCollectionViewHorizontalAlignmentLeft;
sectionThree.headerString = @"Jessica";

FSQExampleCellData *sectionThreeAvatarCell = [FSQExampleCellData new];
sectionThreeAvatarCell.backgroundColor = [UIColor blueColor];
Expand Down
58 changes: 38 additions & 20 deletions FSQCollectionViewAlignedLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
Overview:
FSQCollectionViewAlignedLayout lays out collection view cells sort of like how a type setter would draw out a string,
but with collection cells instead of font glyphs. Each section can have both a vertical and horizontal alignment
(horizontal aligns each line relative to the whole section, vertical aligns the items within each line if they are
but with collection cells instead of font glyphs. Each section can have both a vertical and horizontal alignment
(horizontal aligns each line relative to the whole section, vertical aligns the items within each line if they are
different heights). It also allows you to specify distance between items in each section and between lines.
Each cell can have not only a size, but insets. You can also tell it to insert "line breaks" before or
Each cell can have not only a size, but insets. You can also tell it to insert "line breaks" before or
after each cell to get things to wrap how you want.
You can set defaults for section and cell styles just like you can in Flow Layout. Or you can implement delegate methods:
Expand All @@ -23,7 +23,7 @@
- (FSQCollectionViewAlignedLayoutCellAttributes*)collectionView:layout:attributesForCellAtIndexPath:
To return cell layout information for the specified indexPath.
To return cell layout information for the specified indexPath.
- (CGSize)collectionView:layout:sizeForItemAtIndexPath:remainingLineSpace:
Expand All @@ -39,6 +39,12 @@

@class FSQCollectionViewAlignedLayoutSectionAttributes, FSQCollectionViewAlignedLayoutCellAttributes;

@interface FSQCollectionViewAlignedLayoutInvalidationContext : UICollectionViewLayoutInvalidationContext

@property (nonatomic) BOOL invalidateAlignedLayoutAttributes; // if set to NO, aligned layout will keep all layout information, effectively not invalidating - useful for a subclass which invalidates only a piece of itself

@end

@interface FSQCollectionViewAlignedLayout : UICollectionViewLayout <NSFastEnumeration>

/**
Expand All @@ -48,11 +54,11 @@
*/
@property (nonatomic) IBInspectable CGSize defaultCellSize;

/**
/**
Used if attributesForSectionAtIndex delegate method is not implemented
Defaults to [FSQCollectionViewAlignedLayoutSectionAttributes topLeftAlignment] if not set.
*/
*/
@property (nonatomic) FSQCollectionViewAlignedLayoutSectionAttributes *defaultSectionAttributes;

/**
Expand All @@ -62,14 +68,14 @@
*/
@property (nonatomic) FSQCollectionViewAlignedLayoutCellAttributes *defaultCellAttributes;

/**
/**
Space in points between the bottom most part of a section and the top most part of the next one.
Defaults to 10 if not set.
*/
@property (nonatomic) IBInspectable CGFloat sectionSpacing;

/**
/**
Insets in points around the entire contents of the collection. Defaults to (5, 5, 5, 5) if not set
*/
@property (nonatomic) UIEdgeInsets contentInsets;
Expand All @@ -88,7 +94,7 @@
@param indexPath The index path of the item.
@param remainingLineSpace The amount of space in pts remaining on the line the layout is currently laying out.
@return The size the cell should be. If you return a size whose width is less than or equal to @c remainingLineSpace
@return The size the cell should be. If you return a size whose width is less than or equal to @c remainingLineSpace
it will be laid out on the same lane.
@note remainingLineSpace takes into account any insets that may exist for the current cell, subtracting the
Expand All @@ -99,6 +105,18 @@
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
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.
*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceHeightForHeaderInSection:(NSInteger)section;

/**
Used instead of defaultSectionAttributes if implemented.
Expand Down Expand Up @@ -223,16 +241,16 @@ typedef NS_ENUM(NSInteger, FSQCollectionViewVerticalAlignment) {
*/
@interface FSQCollectionViewAlignedLayoutCellAttributes : NSObject

/**
Insets will be added to size for layout purposes, but the collection cell will end up actually being the size reported
/**
Insets will be added to size for layout purposes, but the collection cell will end up actually being the size reported
in either the sizeForItemAtIndexPath or the layout's defaultCellSize property.
You can add more padding around cells with positive insets,
You can add more padding around cells with positive insets,
or effectively shrink cell/line spacing or make cells overlap by using negative insets.
*/
@property (nonatomic, readonly) UIEdgeInsets insets;

/**
/**
If YES, ensures this cell is the first thing on the line by inserting a line break before if necessary
If there was going to be a line break before anyway, this has no effect (does not insert an EXTRA newline)
Expand All @@ -249,20 +267,20 @@ typedef NS_ENUM(NSInteger, FSQCollectionViewVerticalAlignment) {
/**
If YES and section alignment is Left or Right, future lines will start from this cell's left or right edge respectively.
The available width of all future lines will be lowered and padding will be added to the appropriate side to inset
The available width of all future lines will be lowered and padding will be added to the appropriate side to inset
future lines
@note There is no way to stop indenting once you start it without creating a new section, although you can start a new
@note There is no way to stop indenting once you start it without creating a new section, although you can start a new
indentation from a different cell.
@note The alignment is from the actual position of the cell, not including its insets. Therefore you can fake an
@note The alignment is from the actual position of the cell, not including its insets. Therefore you can fake an
"unindentation" by using negative insets and then starting a new indentation.
*/
@property (nonatomic, readonly) BOOL startLineIndentation;

/**
Reusable shared pointer to a simple cell attribute object.
Zero insets, no line breaks, no indentation.
/**
Reusable shared pointer to a simple cell attribute object.
Zero insets, no line breaks, no indentation.
*/
+ (FSQCollectionViewAlignedLayoutCellAttributes *)defaultCellAttributes;

Expand All @@ -281,4 +299,4 @@ typedef NS_ENUM(NSInteger, FSQCollectionViewVerticalAlignment) {
shouldEndLine:(BOOL)shouldEndLine
startLineIndentation:(BOOL)startLineIndentation;

@end
@end
Loading

0 comments on commit b7ea95d

Please sign in to comment.