├── .gitignore ├── LICENSE ├── README.md ├── SBTableLayout.podspec ├── SBTableLayout ├── SBCollectionViewTableCell.h ├── SBCollectionViewTableCell.m ├── SBCollectionViewTableCellSeparatorView.h ├── SBCollectionViewTableCellSeparatorView.m ├── SBCollectionViewTableLayout.h ├── SBCollectionViewTableLayout.m ├── SBCollectionViewTableLayoutAttributes.h ├── SBCollectionViewTableLayoutAttributes.m ├── SBCollectionViewTableSupplementaryView.h ├── SBCollectionViewTableSupplementaryView.m ├── UIColor+SBCollectionViewTableLayoutColors.h └── UIColor+SBCollectionViewTableLayoutColors.m └── SBTableLayoutDemo ├── SBTableLayoutDemo.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── SBTableLayoutDemo ├── Base.lproj │ └── Main.storyboard ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── SBAppDelegate.h ├── SBAppDelegate.m ├── SBTableLayoutDemo-Info.plist ├── SBTableLayoutDemo-Prefix.pch ├── SBTableLayoutViewController.h ├── SBTableLayoutViewController.m ├── SBTableViewController.h ├── SBTableViewController.m ├── en.lproj │ └── InfoPlist.strings └── main.m └── SBTableLayoutDemoTests ├── SBTableLayoutDemoTests-Info.plist ├── SBTableLayoutDemoTests.m └── en.lproj └── InfoPlist.strings /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | #CocoaPods 21 | Pods 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Simon Blommegård 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SBTableLayout 2 | A customizable UICollectionViewLayout to use instead of UITableView. 3 | 4 | ## Why? 5 | * I like to use UICollectionView way more than UITableView, create custom insert/removal animations, way more flexibility overall. 6 | * Dealing with separators has always been a huge mess on table view cells, I tried to do it exacly the way Apple does on the UITableView, but transparent for the user. 7 | * iOS6 support, the grouped styled UITableView looks horroble on iOS6, this gives you the new look on iOS6 as well. 8 | * Use the cleaner and not so much bloated UITableViewCell is quite nice. 9 | * UITableView has a lot of wied margins, here you have full control over the layout. 10 | 11 | ## Adding to Your Project 12 | * Add all files in the SBTableLayout-folder to your project, and you are good to go. 13 | * …or use [Cocoapods](http://cocoapods.org/): 14 | 15 | ```ruby 16 | pod "SBTableLayout" 17 | ``` 18 | 19 | ## Todo 20 | * Add style for the plain UITableView style. 21 | 22 | ## License 23 | SBTableLayout is released under the MIT-license (see the LICENSE file) 24 | -------------------------------------------------------------------------------- /SBTableLayout.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "SBTableLayout" 3 | s.version = "0.0.2" 4 | s.summary = "A customizable UICollectionViewLayout to use instead of a grouped styled UITableView" 5 | s.homepage = "https://github.com/blommegard/SBTableLayout" 6 | s.license = { :type => 'MIT', :file => 'LICENSE' } 7 | s.author = { "Simon Blommegård" => "simon@blommegard.se" } 8 | s.platform = :ios, '6.0' 9 | s.source = { :git => "https://github.com/blommegard/SBTableLayout.git", :tag => s.version.to_s } 10 | s.source_files = 'SBTableLayout' 11 | s.framework = 'UIKit' 12 | s.requires_arc = true 13 | end 14 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableCell.h 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | @class SBCollectionViewTableCellSeparatorView; 11 | 12 | /** 13 | The class of a table cell in the layout, handles the separator views. 14 | */ 15 | @interface SBCollectionViewTableCell : UICollectionViewCell 16 | 17 | /** 18 | The separator view displayd at the top of top and single cells. 19 | */ 20 | @property (nonatomic, strong) SBCollectionViewTableCellSeparatorView *topSeparatorView; 21 | 22 | /** 23 | The separator view displayd at the bottom of bottom and single cells. 24 | */ 25 | @property (nonatomic, strong) SBCollectionViewTableCellSeparatorView *bottomSeparatorView; 26 | 27 | /** 28 | The separator view displayd at the bottom of top and middle cells. 29 | */ 30 | @property (nonatomic, strong) SBCollectionViewTableCellSeparatorView *middleSeparatorView; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableCell.h 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "SBCollectionViewTableCell.h" 10 | #import "SBCollectionViewTableLayoutAttributes.h" 11 | #import "SBCollectionViewTableCellSeparatorView.h" 12 | #import "UIColor+SBCollectionViewTableLayoutColors.h" 13 | 14 | @implementation SBCollectionViewTableCell 15 | 16 | - (id)initWithFrame:(CGRect)frame { 17 | if (self = [super initWithFrame:frame]) { 18 | UIView *backgroundView = [[UIView alloc] initWithFrame:self.bounds]; 19 | [backgroundView setBackgroundColor:[UIColor sb_cellBackgroundColor]]; 20 | [self setBackgroundView:backgroundView]; 21 | 22 | UIView *selectedBackgroundView = [[UIView alloc] initWithFrame:self.bounds]; 23 | [selectedBackgroundView setBackgroundColor:[UIColor sb_cellSelectedBacgroundColor]]; 24 | [self setSelectedBackgroundView:selectedBackgroundView]; 25 | 26 | _topSeparatorView = [SBCollectionViewTableCellSeparatorView new]; 27 | _bottomSeparatorView = [SBCollectionViewTableCellSeparatorView new]; 28 | _middleSeparatorView = [SBCollectionViewTableCellSeparatorView new]; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)layoutSubviews { 34 | [super layoutSubviews]; 35 | 36 | [self bringSubviewToFront:self.topSeparatorView]; 37 | [self bringSubviewToFront:self.bottomSeparatorView]; 38 | } 39 | 40 | - (void)applyLayoutAttributes:(SBCollectionViewTableLayoutAttributes *)layoutAttributes { 41 | [super applyLayoutAttributes:layoutAttributes]; 42 | 43 | SBCollectionViewTableCellType type = layoutAttributes.cellType; 44 | 45 | CGRect topFrame = CGRectMake(0.f, 46 | 0.f, 47 | CGRectGetWidth(self.bounds), 48 | layoutAttributes.borderSeparatorWidth); 49 | CGRect bottomFrame = CGRectMake(0.f, 50 | CGRectGetHeight(self.bounds)-layoutAttributes.borderSeparatorWidth, 51 | CGRectGetWidth(self.bounds), 52 | layoutAttributes.borderSeparatorWidth); 53 | CGRect middleFrame = CGRectMake(layoutAttributes.middleSeparatorInset.left, 54 | CGRectGetHeight(self.bounds)-layoutAttributes.middleSeparatorWidth, 55 | CGRectGetWidth(self.bounds)-layoutAttributes.middleSeparatorInset.left+layoutAttributes.middleSeparatorInset.right, 56 | layoutAttributes.middleSeparatorWidth); 57 | 58 | [self.topSeparatorView setFrame:topFrame]; 59 | [self.bottomSeparatorView setFrame:bottomFrame]; 60 | [self.middleSeparatorView setFrame:middleFrame]; 61 | 62 | if ((type == SBCollectionViewTableCellTypeTop || type == SBCollectionViewTableCellTypeSingle)) 63 | [self addSubview:self.topSeparatorView]; 64 | else if (self.topSeparatorView.superview) 65 | [self.topSeparatorView removeFromSuperview]; 66 | 67 | if ((type == SBCollectionViewTableCellTypeBottom || type == SBCollectionViewTableCellTypeSingle)) 68 | [self addSubview:self.bottomSeparatorView]; 69 | else if (self.bottomSeparatorView.superview) 70 | [self.bottomSeparatorView removeFromSuperview]; 71 | 72 | if ((type == SBCollectionViewTableCellTypeMiddle || type == SBCollectionViewTableCellTypeTop)) 73 | [self addSubview:self.middleSeparatorView]; 74 | else if (self.middleSeparatorView.superview) 75 | [self.middleSeparatorView removeFromSuperview]; 76 | } 77 | 78 | - (void)setHighlighted:(BOOL)highlighted { 79 | [super setHighlighted:highlighted]; 80 | 81 | [self adjustSeparatorViewsToSelectionAndHighlight:highlighted]; 82 | } 83 | 84 | - (void)setSelected:(BOOL)selected { 85 | [super setSelected:selected]; 86 | 87 | [self adjustSeparatorViewsToSelectionAndHighlight:selected]; 88 | } 89 | 90 | #pragma mark - Private 91 | 92 | // TODO: We should have a better way of doing this. =/ 93 | - (void)adjustSeparatorViewsToSelectionAndHighlight:(BOOL)selected { 94 | UICollectionView *collectionView = (UICollectionView *)self.superview; 95 | NSIndexPath *selfIndexPath = [collectionView indexPathForCell:self]; 96 | SBCollectionViewTableCell *cell = (SBCollectionViewTableCell *)[collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:selfIndexPath.item-1 inSection:selfIndexPath.section]]; 97 | 98 | [self.bottomSeparatorView.superview?self.bottomSeparatorView:self.middleSeparatorView setHidden:selected]; 99 | [cell.bottomSeparatorView.superview?cell.bottomSeparatorView:cell.middleSeparatorView setHidden:selected]; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableCellSeparatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableCellSeparatorView.h 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | The class of a separator used in the cells. 13 | */ 14 | @interface SBCollectionViewTableCellSeparatorView : UIView 15 | @end 16 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableCellSeparatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableCellSeparatorView.m 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "SBCollectionViewTableCellSeparatorView.h" 10 | #import "UIColor+SBCollectionViewTableLayoutColors.h" 11 | 12 | @implementation SBCollectionViewTableCellSeparatorView 13 | 14 | - (id)initWithFrame:(CGRect)frame { 15 | if (self = [super initWithFrame:frame]) { 16 | [self setBackgroundColor:[UIColor sb_cellSeparatorColor]]; 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableLayout.h 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | Protocol for seting the properties on a section basis instead of the whole layout 13 | */ 14 | @protocol SBCollectionViewDelegateTableLayout 15 | @optional 16 | 17 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout middleSeparatorInsetForSectionAntIndex:(NSInteger)section; 18 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout borderSeparatorWidthForSectionAntIndex:(NSInteger)section; 19 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout middleSeparatorWidthForSectionAntIndex:(NSInteger)section; 20 | 21 | @end 22 | 23 | /** 24 | The layout calculating and collection the different properties. 25 | */ 26 | @interface SBCollectionViewTableLayout : UICollectionViewFlowLayout 27 | 28 | /** 29 | Inset of the middle separator, only the left and right values are respected. Defaults to L=15.f, R=0.f 30 | */ 31 | @property (nonatomic) UIEdgeInsets middleSeparatorInset; 32 | 33 | /** 34 | The border thickness of the separators at the top and bottom of a secion. Defaults to 1.f/scale 35 | */ 36 | @property (nonatomic) CGFloat borderSeparatorWidth; 37 | 38 | /** 39 | The border thickness of the middle separators. Defaults to 1.f/scale 40 | */ 41 | @property (nonatomic) CGFloat middleSeparatorWidth; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableLayout.m 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "SBCollectionViewTableLayout.h" 10 | #import "SBCollectionViewTableLayoutAttributes.h" 11 | 12 | @interface SBCollectionViewTableLayout () 13 | @property (nonatomic) UIEdgeInsets *middleSeparatorInsets; 14 | @property (nonatomic) CGFloat *borderSeparatorWidths; 15 | @property (nonatomic) CGFloat *middleSeparatorWidths; 16 | @end 17 | 18 | @implementation SBCollectionViewTableLayout 19 | 20 | + (Class)layoutAttributesClass { 21 | return [SBCollectionViewTableLayoutAttributes class]; 22 | } 23 | 24 | - (id)init { 25 | if (self = [super init]) { 26 | CGFloat scale = [UIScreen mainScreen].scale; 27 | 28 | _middleSeparatorInset = UIEdgeInsetsMake(0.f, 15.f, 0.f, 0.f); 29 | _borderSeparatorWidth = 1.f/scale; 30 | _middleSeparatorWidth = 1.f/scale; 31 | 32 | [self setMinimumLineSpacing:0.f]; 33 | [self setMinimumInteritemSpacing:0.f]; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)dealloc { 40 | if (_middleSeparatorInsets) free(_middleSeparatorInsets); 41 | if (_borderSeparatorWidths) free(_borderSeparatorWidths); 42 | if (_middleSeparatorWidths) free(_middleSeparatorWidths); 43 | } 44 | 45 | - (void)prepareLayout { 46 | [super prepareLayout]; 47 | 48 | id delegate = (id )self.collectionView.delegate; 49 | BOOL inset = [delegate respondsToSelector:@selector(collectionView:layout:middleSeparatorInsetForSectionAntIndex:)]; 50 | BOOL borderWidth = [delegate respondsToSelector:@selector(collectionView:layout:borderSeparatorWidthForSectionAntIndex:)]; 51 | BOOL middleWidth = [delegate respondsToSelector:@selector(collectionView:layout:middleSeparatorWidthForSectionAntIndex:)]; 52 | 53 | 54 | if (inset || borderWidth || middleWidth) { 55 | NSInteger sections = [self.collectionView numberOfSections]; 56 | 57 | // TODO: realloc 58 | if (_middleSeparatorInsets) free(_middleSeparatorInsets); 59 | if (inset) _middleSeparatorInsets = malloc(sizeof(UIEdgeInsets)*sections); 60 | 61 | if (_borderSeparatorWidths) free(_borderSeparatorWidths); 62 | if (borderWidth) _borderSeparatorWidths = malloc(sizeof(CGFloat)*sections); 63 | 64 | if (_middleSeparatorWidths) free(_middleSeparatorWidths); 65 | if (middleWidth) _middleSeparatorWidths = malloc(sizeof(CGFloat)*sections); 66 | 67 | 68 | for (NSInteger section = 0; section < sections; section++) { 69 | if (inset) 70 | _middleSeparatorInsets[section] = [delegate collectionView:self.collectionView 71 | layout:self 72 | middleSeparatorInsetForSectionAntIndex:section]; 73 | 74 | if (borderWidth) 75 | _borderSeparatorWidths[section] = [delegate collectionView:self.collectionView 76 | layout:self 77 | borderSeparatorWidthForSectionAntIndex:section]; 78 | 79 | if (middleWidth) 80 | _middleSeparatorWidths[section] = [delegate collectionView:self.collectionView 81 | layout:self 82 | middleSeparatorWidthForSectionAntIndex:section]; 83 | } 84 | } 85 | 86 | } 87 | 88 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 89 | NSArray *allAttributes = [super layoutAttributesForElementsInRect:rect]; 90 | NSMutableArray *array = [NSMutableArray arrayWithArray:allAttributes]; 91 | 92 | for (SBCollectionViewTableLayoutAttributes *attributes in allAttributes) 93 | if (attributes.representedElementCategory == UICollectionElementCategoryCell) { 94 | NSIndexPath *indexPath = attributes.indexPath; 95 | NSInteger rows = [self.collectionView numberOfItemsInSection:indexPath.section]; 96 | 97 | if (indexPath.row == 0) 98 | [attributes setCellType:(rows == 1)?SBCollectionViewTableCellTypeSingle:SBCollectionViewTableCellTypeTop]; 99 | else if (indexPath.row == (rows-1)) 100 | [attributes setCellType:SBCollectionViewTableCellTypeBottom]; 101 | else 102 | [attributes setCellType:SBCollectionViewTableCellTypeMiddle]; 103 | 104 | [attributes setMiddleSeparatorInset:_middleSeparatorInsets?_middleSeparatorInsets[indexPath.section]:_middleSeparatorInset]; 105 | [attributes setBorderSeparatorWidth:_borderSeparatorWidths?_borderSeparatorWidths[indexPath.section]:_borderSeparatorWidth]; 106 | [attributes setMiddleSeparatorWidth:_middleSeparatorWidths?_middleSeparatorWidths[indexPath.section]:_middleSeparatorWidth]; 107 | } 108 | 109 | return [array copy]; 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableLayoutAttributes.h: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableLayoutAttributes.h 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, SBCollectionViewTableCellType) { 12 | SBCollectionViewTableCellTypeTop, 13 | SBCollectionViewTableCellTypeMiddle, 14 | SBCollectionViewTableCellTypeBottom, 15 | SBCollectionViewTableCellTypeSingle 16 | }; 17 | 18 | /** 19 | The custom layout attributes class for storing information about the separators. 20 | This class i populated by the layout class. 21 | */ 22 | @interface SBCollectionViewTableLayoutAttributes : UICollectionViewLayoutAttributes 23 | 24 | /** 25 | Type of the cell, top, middle, bottom or single. 26 | */ 27 | @property (nonatomic) SBCollectionViewTableCellType cellType; 28 | 29 | /** 30 | Inset of the middle separator, only the left and right values are respected. Defaults to L=15.f, R=0.f 31 | */ 32 | @property (nonatomic) UIEdgeInsets middleSeparatorInset; 33 | 34 | /** 35 | The border thickness of the separators at the top and bottom of a secion. Defaults to 1.f/scale 36 | */ 37 | @property (nonatomic) CGFloat borderSeparatorWidth; 38 | 39 | /** 40 | The border thickness of the middle separators. Defaults to 1.f/scale 41 | */ 42 | @property (nonatomic) CGFloat middleSeparatorWidth; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableLayoutAttributes.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableLayoutAttributes.m 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "SBCollectionViewTableLayoutAttributes.h" 10 | 11 | @implementation SBCollectionViewTableLayoutAttributes 12 | 13 | #pragma mark - NSCopying 14 | 15 | - (id)copyWithZone:(NSZone *)zone { 16 | SBCollectionViewTableLayoutAttributes *attribute = [super copyWithZone:zone]; 17 | attribute->_cellType = _cellType; 18 | attribute->_middleSeparatorInset = _middleSeparatorInset; 19 | attribute->_borderSeparatorWidth = _borderSeparatorWidth; 20 | attribute->_middleSeparatorWidth = _middleSeparatorWidth; 21 | return attribute; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableSupplementaryView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableSupplementaryView.h 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | A helper class to create footer/header views looking like the ones on a grouped UITableView 13 | */ 14 | @interface SBCollectionViewTableSupplementaryView : UICollectionReusableView 15 | 16 | /** 17 | Label pre sized accordingly, inseted 10pt from every edge, numberOfLined set to 0. 18 | */ 19 | @property (nonatomic, strong) UILabel *label; 20 | 21 | /** 22 | Ruturns the size (calculated height + width) for the whole view. 23 | 24 | @param width The bounding width for the view, this will be returned as the width as well. 25 | 26 | @param string The atteributed string to be rendered by the label in this view. 27 | 28 | @return Ruturns the size (calculated height + width) for the whole view. 29 | */ 30 | + (CGSize)sizeForWidth:(CGFloat)width atteributedString:(NSAttributedString *)string; 31 | 32 | /** 33 | Ruturns an attributet string with matching style as the header/footer for UITableView. 34 | 35 | @param kind The kind of supplementary element, only UICollectionElementKindSectionHeader or UICollectionElementKindSectionFooter is supported. 36 | 37 | @param text The text to be rendered. 38 | 39 | @return Ruturns an attributet string with matching style as the header/footer for UITableView. 40 | */ 41 | + (NSAttributedString *)atteributedStringForKind:(NSString *)kind text:(NSString *)text; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /SBTableLayout/SBCollectionViewTableSupplementaryView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBCollectionViewTableSupplementaryView.m 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "SBCollectionViewTableSupplementaryView.h" 10 | #import "UIColor+SBCollectionViewTableLayoutColors.h" 11 | 12 | static UIEdgeInsets paddning = {10.f, 12.f, 10.f, 10.f}; 13 | 14 | @implementation SBCollectionViewTableSupplementaryView 15 | 16 | - (id)initWithFrame:(CGRect)frame { 17 | if (self = [super initWithFrame:frame]) { 18 | [self addSubview:self.label]; 19 | } 20 | return self; 21 | } 22 | 23 | #pragma mark - Properties 24 | 25 | - (UILabel *)label { 26 | if (!_label) { 27 | _label = [[UILabel alloc] initWithFrame:UIEdgeInsetsInsetRect(self.bounds, paddning)]; 28 | [_label setBackgroundColor:[UIColor sb_tableBackgroundColor]]; 29 | [_label setTextColor:[UIColor sb_supplementaryViewTextColor]]; 30 | [_label setNumberOfLines:0]; 31 | } 32 | return _label; 33 | } 34 | 35 | #pragma mark - 36 | 37 | + (CGSize)sizeForWidth:(CGFloat)width atteributedString:(NSAttributedString *)string { 38 | CGRect rect = [string boundingRectWithSize:CGSizeMake(width-paddning.left-paddning.right, CGFLOAT_MAX) 39 | options:(NSStringDrawingUsesLineFragmentOrigin) 40 | context:nil]; 41 | 42 | return CGSizeMake(width, CGRectGetHeight(rect)+paddning.top+paddning.bottom); 43 | } 44 | 45 | + (NSAttributedString *)atteributedStringForKind:(NSString *)kind text:(NSString *)text { 46 | NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 47 | [paragraphStyle setAlignment:NSTextAlignmentLeft]; 48 | UIFont *font; 49 | 50 | if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { 51 | font = [UIFont systemFontOfSize:14.f]; 52 | text = [text uppercaseString]; 53 | } 54 | else { 55 | font = [UIFont systemFontOfSize:12.f]; 56 | } 57 | 58 | NSDictionary *attributes = @{ 59 | NSFontAttributeName:font, 60 | NSParagraphStyleAttributeName:paragraphStyle, 61 | }; 62 | 63 | return [[NSAttributedString alloc] initWithString:text attributes:attributes]; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /SBTableLayout/UIColor+SBCollectionViewTableLayoutColors.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+SBCollectionViewTableLayoutColors.h 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | A helper class with the default colors a grouped UITableView uses. 13 | */ 14 | @interface UIColor (SBCollectionViewTableLayoutColors) 15 | 16 | /** 17 | Returns the default color of a separator used in a grouped UITableView 18 | 19 | @return Returns the default color of a separator used in a grouped UITableView 20 | */ 21 | + (UIColor *)sb_cellSeparatorColor; 22 | 23 | /** 24 | Returns the default color of a cell background used in a grouped UITableView 25 | 26 | @return Returns the default color of a cell background used in a grouped UITableView 27 | */+ (UIColor *)sb_cellBackgroundColor; 28 | 29 | /** 30 | Returns the default color of a selected cell background used in a grouped UITableView 31 | 32 | @return Returns the default color of a selected cell background used in a grouped UITableView 33 | */ 34 | + (UIColor *)sb_cellSelectedBacgroundColor; 35 | 36 | /** 37 | Returns the default color of the background in a grouped UITableView 38 | 39 | @return Returns the default color of the background in a grouped UITableView 40 | */ 41 | + (UIColor *)sb_tableBackgroundColor; 42 | 43 | /** 44 | Returns the default text color of the header / footer text in a grouped UITableView 45 | 46 | @return Returns the default text color of the header / footer text in a grouped UITableView 47 | */ 48 | + (UIColor *)sb_supplementaryViewTextColor; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /SBTableLayout/UIColor+SBCollectionViewTableLayoutColors.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+SBCollectionViewTableLayoutColors.m 3 | // SBTableLayout 4 | // 5 | // Created by Simon Blommegård on 2013-11-11. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "UIColor+SBCollectionViewTableLayoutColors.h" 10 | 11 | @implementation UIColor (SBCollectionViewTableLayoutColors) 12 | 13 | + (UIColor *)sb_cellSeparatorColor { 14 | return [UIColor colorWithRed:0.784 green:0.780 blue:0.800 alpha:1.000]; 15 | } 16 | 17 | + (UIColor *)sb_cellBackgroundColor { 18 | return [UIColor whiteColor]; 19 | } 20 | 21 | + (UIColor *)sb_cellSelectedBacgroundColor { 22 | return [UIColor colorWithWhite:0.851 alpha:1.000]; 23 | } 24 | 25 | + (UIColor *)sb_tableBackgroundColor { 26 | return [UIColor colorWithRed:0.937 green:0.937 blue:0.957 alpha:1.000]; 27 | } 28 | 29 | + (UIColor *)sb_supplementaryViewTextColor { 30 | return [UIColor colorWithRed:0.427 green:0.427 blue:0.447 alpha:1.000]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F44397F918306CD00024C0A9 /* UIColor+SBCollectionViewTableLayoutColors.m in Sources */ = {isa = PBXBuildFile; fileRef = F44397F818306CD00024C0A9 /* UIColor+SBCollectionViewTableLayoutColors.m */; }; 11 | F44397FE183195360024C0A9 /* SBCollectionViewTableCellSeparatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = F44397FD183195360024C0A9 /* SBCollectionViewTableCellSeparatorView.m */; }; 12 | F4C4201C183059C70054BE75 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C4201B183059C70054BE75 /* Foundation.framework */; }; 13 | F4C4201E183059C70054BE75 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C4201D183059C70054BE75 /* CoreGraphics.framework */; }; 14 | F4C42020183059C70054BE75 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C4201F183059C70054BE75 /* UIKit.framework */; }; 15 | F4C42026183059C70054BE75 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F4C42024183059C70054BE75 /* InfoPlist.strings */; }; 16 | F4C42028183059C70054BE75 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C42027183059C70054BE75 /* main.m */; }; 17 | F4C4202C183059C70054BE75 /* SBAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4202B183059C70054BE75 /* SBAppDelegate.m */; }; 18 | F4C4202F183059C70054BE75 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F4C4202D183059C70054BE75 /* Main.storyboard */; }; 19 | F4C42034183059C70054BE75 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4C42033183059C70054BE75 /* Images.xcassets */; }; 20 | F4C4203B183059C70054BE75 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C4203A183059C70054BE75 /* XCTest.framework */; }; 21 | F4C4203C183059C70054BE75 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C4201B183059C70054BE75 /* Foundation.framework */; }; 22 | F4C4203D183059C70054BE75 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C4201F183059C70054BE75 /* UIKit.framework */; }; 23 | F4C42045183059C70054BE75 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F4C42043183059C70054BE75 /* InfoPlist.strings */; }; 24 | F4C42047183059C70054BE75 /* SBTableLayoutDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C42046183059C70054BE75 /* SBTableLayoutDemoTests.m */; }; 25 | F4C4206518305A930054BE75 /* SBCollectionViewTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4205E18305A930054BE75 /* SBCollectionViewTableCell.m */; }; 26 | F4C4206618305A930054BE75 /* SBCollectionViewTableLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4206018305A930054BE75 /* SBCollectionViewTableLayout.m */; }; 27 | F4C4206718305A930054BE75 /* SBCollectionViewTableLayoutAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4206218305A930054BE75 /* SBCollectionViewTableLayoutAttributes.m */; }; 28 | F4C4206818305A930054BE75 /* SBCollectionViewTableSupplementaryView.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4206418305A930054BE75 /* SBCollectionViewTableSupplementaryView.m */; }; 29 | F4C4206B183063420054BE75 /* SBTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4206A183063420054BE75 /* SBTableViewController.m */; }; 30 | F4C4206E183063660054BE75 /* SBTableLayoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C4206D183063660054BE75 /* SBTableLayoutViewController.m */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | F4C4203E183059C70054BE75 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = F4C42010183059C70054BE75 /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = F4C42017183059C70054BE75; 39 | remoteInfo = SBTableLayoutDemo; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | F44397F718306CD00024C0A9 /* UIColor+SBCollectionViewTableLayoutColors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+SBCollectionViewTableLayoutColors.h"; sourceTree = ""; }; 45 | F44397F818306CD00024C0A9 /* UIColor+SBCollectionViewTableLayoutColors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+SBCollectionViewTableLayoutColors.m"; sourceTree = ""; }; 46 | F44397FC183195360024C0A9 /* SBCollectionViewTableCellSeparatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBCollectionViewTableCellSeparatorView.h; sourceTree = ""; }; 47 | F44397FD183195360024C0A9 /* SBCollectionViewTableCellSeparatorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBCollectionViewTableCellSeparatorView.m; sourceTree = ""; }; 48 | F4C42018183059C70054BE75 /* SBTableLayoutDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SBTableLayoutDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | F4C4201B183059C70054BE75 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 50 | F4C4201D183059C70054BE75 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 51 | F4C4201F183059C70054BE75 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 52 | F4C42023183059C70054BE75 /* SBTableLayoutDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SBTableLayoutDemo-Info.plist"; sourceTree = ""; }; 53 | F4C42025183059C70054BE75 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 54 | F4C42027183059C70054BE75 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 55 | F4C42029183059C70054BE75 /* SBTableLayoutDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SBTableLayoutDemo-Prefix.pch"; sourceTree = ""; }; 56 | F4C4202A183059C70054BE75 /* SBAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBAppDelegate.h; sourceTree = ""; }; 57 | F4C4202B183059C70054BE75 /* SBAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBAppDelegate.m; sourceTree = ""; }; 58 | F4C4202E183059C70054BE75 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 59 | F4C42033183059C70054BE75 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 60 | F4C42039183059C70054BE75 /* SBTableLayoutDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SBTableLayoutDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | F4C4203A183059C70054BE75 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 62 | F4C42042183059C70054BE75 /* SBTableLayoutDemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SBTableLayoutDemoTests-Info.plist"; sourceTree = ""; }; 63 | F4C42044183059C70054BE75 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 64 | F4C42046183059C70054BE75 /* SBTableLayoutDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBTableLayoutDemoTests.m; sourceTree = ""; }; 65 | F4C4205D18305A930054BE75 /* SBCollectionViewTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBCollectionViewTableCell.h; sourceTree = ""; }; 66 | F4C4205E18305A930054BE75 /* SBCollectionViewTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBCollectionViewTableCell.m; sourceTree = ""; }; 67 | F4C4205F18305A930054BE75 /* SBCollectionViewTableLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBCollectionViewTableLayout.h; sourceTree = ""; }; 68 | F4C4206018305A930054BE75 /* SBCollectionViewTableLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBCollectionViewTableLayout.m; sourceTree = ""; }; 69 | F4C4206118305A930054BE75 /* SBCollectionViewTableLayoutAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBCollectionViewTableLayoutAttributes.h; sourceTree = ""; }; 70 | F4C4206218305A930054BE75 /* SBCollectionViewTableLayoutAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBCollectionViewTableLayoutAttributes.m; sourceTree = ""; }; 71 | F4C4206318305A930054BE75 /* SBCollectionViewTableSupplementaryView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBCollectionViewTableSupplementaryView.h; sourceTree = ""; }; 72 | F4C4206418305A930054BE75 /* SBCollectionViewTableSupplementaryView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBCollectionViewTableSupplementaryView.m; sourceTree = ""; }; 73 | F4C42069183063420054BE75 /* SBTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBTableViewController.h; sourceTree = ""; }; 74 | F4C4206A183063420054BE75 /* SBTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBTableViewController.m; sourceTree = ""; }; 75 | F4C4206C183063660054BE75 /* SBTableLayoutViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBTableLayoutViewController.h; sourceTree = ""; }; 76 | F4C4206D183063660054BE75 /* SBTableLayoutViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBTableLayoutViewController.m; sourceTree = ""; }; 77 | /* End PBXFileReference section */ 78 | 79 | /* Begin PBXFrameworksBuildPhase section */ 80 | F4C42015183059C70054BE75 /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | F4C4201E183059C70054BE75 /* CoreGraphics.framework in Frameworks */, 85 | F4C42020183059C70054BE75 /* UIKit.framework in Frameworks */, 86 | F4C4201C183059C70054BE75 /* Foundation.framework in Frameworks */, 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | F4C42036183059C70054BE75 /* Frameworks */ = { 91 | isa = PBXFrameworksBuildPhase; 92 | buildActionMask = 2147483647; 93 | files = ( 94 | F4C4203B183059C70054BE75 /* XCTest.framework in Frameworks */, 95 | F4C4203D183059C70054BE75 /* UIKit.framework in Frameworks */, 96 | F4C4203C183059C70054BE75 /* Foundation.framework in Frameworks */, 97 | ); 98 | runOnlyForDeploymentPostprocessing = 0; 99 | }; 100 | /* End PBXFrameworksBuildPhase section */ 101 | 102 | /* Begin PBXGroup section */ 103 | F4C4200F183059C70054BE75 = { 104 | isa = PBXGroup; 105 | children = ( 106 | F4C4205018305A5C0054BE75 /* SBTableLayout */, 107 | F4C42021183059C70054BE75 /* SBTableLayoutDemo */, 108 | F4C42040183059C70054BE75 /* SBTableLayoutDemoTests */, 109 | F4C4201A183059C70054BE75 /* Frameworks */, 110 | F4C42019183059C70054BE75 /* Products */, 111 | ); 112 | sourceTree = ""; 113 | }; 114 | F4C42019183059C70054BE75 /* Products */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | F4C42018183059C70054BE75 /* SBTableLayoutDemo.app */, 118 | F4C42039183059C70054BE75 /* SBTableLayoutDemoTests.xctest */, 119 | ); 120 | name = Products; 121 | sourceTree = ""; 122 | }; 123 | F4C4201A183059C70054BE75 /* Frameworks */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | F4C4201B183059C70054BE75 /* Foundation.framework */, 127 | F4C4201D183059C70054BE75 /* CoreGraphics.framework */, 128 | F4C4201F183059C70054BE75 /* UIKit.framework */, 129 | F4C4203A183059C70054BE75 /* XCTest.framework */, 130 | ); 131 | name = Frameworks; 132 | sourceTree = ""; 133 | }; 134 | F4C42021183059C70054BE75 /* SBTableLayoutDemo */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | F4C4202A183059C70054BE75 /* SBAppDelegate.h */, 138 | F4C4202B183059C70054BE75 /* SBAppDelegate.m */, 139 | F4C4202D183059C70054BE75 /* Main.storyboard */, 140 | F4C42033183059C70054BE75 /* Images.xcassets */, 141 | F4C42022183059C70054BE75 /* Supporting Files */, 142 | F4C42069183063420054BE75 /* SBTableViewController.h */, 143 | F4C4206A183063420054BE75 /* SBTableViewController.m */, 144 | F4C4206C183063660054BE75 /* SBTableLayoutViewController.h */, 145 | F4C4206D183063660054BE75 /* SBTableLayoutViewController.m */, 146 | ); 147 | path = SBTableLayoutDemo; 148 | sourceTree = ""; 149 | }; 150 | F4C42022183059C70054BE75 /* Supporting Files */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | F4C42023183059C70054BE75 /* SBTableLayoutDemo-Info.plist */, 154 | F4C42024183059C70054BE75 /* InfoPlist.strings */, 155 | F4C42027183059C70054BE75 /* main.m */, 156 | F4C42029183059C70054BE75 /* SBTableLayoutDemo-Prefix.pch */, 157 | ); 158 | name = "Supporting Files"; 159 | sourceTree = ""; 160 | }; 161 | F4C42040183059C70054BE75 /* SBTableLayoutDemoTests */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | F4C42046183059C70054BE75 /* SBTableLayoutDemoTests.m */, 165 | F4C42041183059C70054BE75 /* Supporting Files */, 166 | ); 167 | path = SBTableLayoutDemoTests; 168 | sourceTree = ""; 169 | }; 170 | F4C42041183059C70054BE75 /* Supporting Files */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | F4C42042183059C70054BE75 /* SBTableLayoutDemoTests-Info.plist */, 174 | F4C42043183059C70054BE75 /* InfoPlist.strings */, 175 | ); 176 | name = "Supporting Files"; 177 | sourceTree = ""; 178 | }; 179 | F4C4205018305A5C0054BE75 /* SBTableLayout */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | F4C4205D18305A930054BE75 /* SBCollectionViewTableCell.h */, 183 | F4C4205E18305A930054BE75 /* SBCollectionViewTableCell.m */, 184 | F4C4205F18305A930054BE75 /* SBCollectionViewTableLayout.h */, 185 | F4C4206018305A930054BE75 /* SBCollectionViewTableLayout.m */, 186 | F4C4206118305A930054BE75 /* SBCollectionViewTableLayoutAttributes.h */, 187 | F4C4206218305A930054BE75 /* SBCollectionViewTableLayoutAttributes.m */, 188 | F4C4206318305A930054BE75 /* SBCollectionViewTableSupplementaryView.h */, 189 | F4C4206418305A930054BE75 /* SBCollectionViewTableSupplementaryView.m */, 190 | F44397F718306CD00024C0A9 /* UIColor+SBCollectionViewTableLayoutColors.h */, 191 | F44397F818306CD00024C0A9 /* UIColor+SBCollectionViewTableLayoutColors.m */, 192 | F44397FC183195360024C0A9 /* SBCollectionViewTableCellSeparatorView.h */, 193 | F44397FD183195360024C0A9 /* SBCollectionViewTableCellSeparatorView.m */, 194 | ); 195 | name = SBTableLayout; 196 | path = ../SBTableLayout; 197 | sourceTree = ""; 198 | }; 199 | /* End PBXGroup section */ 200 | 201 | /* Begin PBXNativeTarget section */ 202 | F4C42017183059C70054BE75 /* SBTableLayoutDemo */ = { 203 | isa = PBXNativeTarget; 204 | buildConfigurationList = F4C4204A183059C70054BE75 /* Build configuration list for PBXNativeTarget "SBTableLayoutDemo" */; 205 | buildPhases = ( 206 | F4C42014183059C70054BE75 /* Sources */, 207 | F4C42015183059C70054BE75 /* Frameworks */, 208 | F4C42016183059C70054BE75 /* Resources */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | ); 214 | name = SBTableLayoutDemo; 215 | productName = SBTableLayoutDemo; 216 | productReference = F4C42018183059C70054BE75 /* SBTableLayoutDemo.app */; 217 | productType = "com.apple.product-type.application"; 218 | }; 219 | F4C42038183059C70054BE75 /* SBTableLayoutDemoTests */ = { 220 | isa = PBXNativeTarget; 221 | buildConfigurationList = F4C4204D183059C70054BE75 /* Build configuration list for PBXNativeTarget "SBTableLayoutDemoTests" */; 222 | buildPhases = ( 223 | F4C42035183059C70054BE75 /* Sources */, 224 | F4C42036183059C70054BE75 /* Frameworks */, 225 | F4C42037183059C70054BE75 /* Resources */, 226 | ); 227 | buildRules = ( 228 | ); 229 | dependencies = ( 230 | F4C4203F183059C70054BE75 /* PBXTargetDependency */, 231 | ); 232 | name = SBTableLayoutDemoTests; 233 | productName = SBTableLayoutDemoTests; 234 | productReference = F4C42039183059C70054BE75 /* SBTableLayoutDemoTests.xctest */; 235 | productType = "com.apple.product-type.bundle.unit-test"; 236 | }; 237 | /* End PBXNativeTarget section */ 238 | 239 | /* Begin PBXProject section */ 240 | F4C42010183059C70054BE75 /* Project object */ = { 241 | isa = PBXProject; 242 | attributes = { 243 | CLASSPREFIX = SB; 244 | LastUpgradeCheck = 0500; 245 | ORGANIZATIONNAME = "Simon Blommegård"; 246 | TargetAttributes = { 247 | F4C42038183059C70054BE75 = { 248 | TestTargetID = F4C42017183059C70054BE75; 249 | }; 250 | }; 251 | }; 252 | buildConfigurationList = F4C42013183059C70054BE75 /* Build configuration list for PBXProject "SBTableLayoutDemo" */; 253 | compatibilityVersion = "Xcode 3.2"; 254 | developmentRegion = English; 255 | hasScannedForEncodings = 0; 256 | knownRegions = ( 257 | en, 258 | Base, 259 | ); 260 | mainGroup = F4C4200F183059C70054BE75; 261 | productRefGroup = F4C42019183059C70054BE75 /* Products */; 262 | projectDirPath = ""; 263 | projectRoot = ""; 264 | targets = ( 265 | F4C42017183059C70054BE75 /* SBTableLayoutDemo */, 266 | F4C42038183059C70054BE75 /* SBTableLayoutDemoTests */, 267 | ); 268 | }; 269 | /* End PBXProject section */ 270 | 271 | /* Begin PBXResourcesBuildPhase section */ 272 | F4C42016183059C70054BE75 /* Resources */ = { 273 | isa = PBXResourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | F4C42034183059C70054BE75 /* Images.xcassets in Resources */, 277 | F4C42026183059C70054BE75 /* InfoPlist.strings in Resources */, 278 | F4C4202F183059C70054BE75 /* Main.storyboard in Resources */, 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | F4C42037183059C70054BE75 /* Resources */ = { 283 | isa = PBXResourcesBuildPhase; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | F4C42045183059C70054BE75 /* InfoPlist.strings in Resources */, 287 | ); 288 | runOnlyForDeploymentPostprocessing = 0; 289 | }; 290 | /* End PBXResourcesBuildPhase section */ 291 | 292 | /* Begin PBXSourcesBuildPhase section */ 293 | F4C42014183059C70054BE75 /* Sources */ = { 294 | isa = PBXSourcesBuildPhase; 295 | buildActionMask = 2147483647; 296 | files = ( 297 | F4C4206718305A930054BE75 /* SBCollectionViewTableLayoutAttributes.m in Sources */, 298 | F4C42028183059C70054BE75 /* main.m in Sources */, 299 | F44397F918306CD00024C0A9 /* UIColor+SBCollectionViewTableLayoutColors.m in Sources */, 300 | F44397FE183195360024C0A9 /* SBCollectionViewTableCellSeparatorView.m in Sources */, 301 | F4C4206E183063660054BE75 /* SBTableLayoutViewController.m in Sources */, 302 | F4C4206618305A930054BE75 /* SBCollectionViewTableLayout.m in Sources */, 303 | F4C4206B183063420054BE75 /* SBTableViewController.m in Sources */, 304 | F4C4202C183059C70054BE75 /* SBAppDelegate.m in Sources */, 305 | F4C4206818305A930054BE75 /* SBCollectionViewTableSupplementaryView.m in Sources */, 306 | F4C4206518305A930054BE75 /* SBCollectionViewTableCell.m in Sources */, 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | }; 310 | F4C42035183059C70054BE75 /* Sources */ = { 311 | isa = PBXSourcesBuildPhase; 312 | buildActionMask = 2147483647; 313 | files = ( 314 | F4C42047183059C70054BE75 /* SBTableLayoutDemoTests.m in Sources */, 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | }; 318 | /* End PBXSourcesBuildPhase section */ 319 | 320 | /* Begin PBXTargetDependency section */ 321 | F4C4203F183059C70054BE75 /* PBXTargetDependency */ = { 322 | isa = PBXTargetDependency; 323 | target = F4C42017183059C70054BE75 /* SBTableLayoutDemo */; 324 | targetProxy = F4C4203E183059C70054BE75 /* PBXContainerItemProxy */; 325 | }; 326 | /* End PBXTargetDependency section */ 327 | 328 | /* Begin PBXVariantGroup section */ 329 | F4C42024183059C70054BE75 /* InfoPlist.strings */ = { 330 | isa = PBXVariantGroup; 331 | children = ( 332 | F4C42025183059C70054BE75 /* en */, 333 | ); 334 | name = InfoPlist.strings; 335 | sourceTree = ""; 336 | }; 337 | F4C4202D183059C70054BE75 /* Main.storyboard */ = { 338 | isa = PBXVariantGroup; 339 | children = ( 340 | F4C4202E183059C70054BE75 /* Base */, 341 | ); 342 | name = Main.storyboard; 343 | sourceTree = ""; 344 | }; 345 | F4C42043183059C70054BE75 /* InfoPlist.strings */ = { 346 | isa = PBXVariantGroup; 347 | children = ( 348 | F4C42044183059C70054BE75 /* en */, 349 | ); 350 | name = InfoPlist.strings; 351 | sourceTree = ""; 352 | }; 353 | /* End PBXVariantGroup section */ 354 | 355 | /* Begin XCBuildConfiguration section */ 356 | F4C42048183059C70054BE75 /* Debug */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | ALWAYS_SEARCH_USER_PATHS = NO; 360 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 361 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 362 | CLANG_CXX_LIBRARY = "libc++"; 363 | CLANG_ENABLE_MODULES = YES; 364 | CLANG_ENABLE_OBJC_ARC = YES; 365 | CLANG_WARN_BOOL_CONVERSION = YES; 366 | CLANG_WARN_CONSTANT_CONVERSION = YES; 367 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 368 | CLANG_WARN_EMPTY_BODY = YES; 369 | CLANG_WARN_ENUM_CONVERSION = YES; 370 | CLANG_WARN_INT_CONVERSION = YES; 371 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 372 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 373 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 374 | COPY_PHASE_STRIP = NO; 375 | GCC_C_LANGUAGE_STANDARD = gnu99; 376 | GCC_DYNAMIC_NO_PIC = NO; 377 | GCC_OPTIMIZATION_LEVEL = 0; 378 | GCC_PREPROCESSOR_DEFINITIONS = ( 379 | "DEBUG=1", 380 | "$(inherited)", 381 | ); 382 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 383 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 384 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 385 | GCC_WARN_UNDECLARED_SELECTOR = YES; 386 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 387 | GCC_WARN_UNUSED_FUNCTION = YES; 388 | GCC_WARN_UNUSED_VARIABLE = YES; 389 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 390 | ONLY_ACTIVE_ARCH = YES; 391 | SDKROOT = iphoneos; 392 | }; 393 | name = Debug; 394 | }; 395 | F4C42049183059C70054BE75 /* Release */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ALWAYS_SEARCH_USER_PATHS = NO; 399 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 400 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 401 | CLANG_CXX_LIBRARY = "libc++"; 402 | CLANG_ENABLE_MODULES = YES; 403 | CLANG_ENABLE_OBJC_ARC = YES; 404 | CLANG_WARN_BOOL_CONVERSION = YES; 405 | CLANG_WARN_CONSTANT_CONVERSION = YES; 406 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 407 | CLANG_WARN_EMPTY_BODY = YES; 408 | CLANG_WARN_ENUM_CONVERSION = YES; 409 | CLANG_WARN_INT_CONVERSION = YES; 410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 411 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 412 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 413 | COPY_PHASE_STRIP = YES; 414 | ENABLE_NS_ASSERTIONS = NO; 415 | GCC_C_LANGUAGE_STANDARD = gnu99; 416 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 417 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 418 | GCC_WARN_UNDECLARED_SELECTOR = YES; 419 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 420 | GCC_WARN_UNUSED_FUNCTION = YES; 421 | GCC_WARN_UNUSED_VARIABLE = YES; 422 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 423 | SDKROOT = iphoneos; 424 | VALIDATE_PRODUCT = YES; 425 | }; 426 | name = Release; 427 | }; 428 | F4C4204B183059C70054BE75 /* Debug */ = { 429 | isa = XCBuildConfiguration; 430 | buildSettings = { 431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 432 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 433 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 434 | GCC_PREFIX_HEADER = "SBTableLayoutDemo/SBTableLayoutDemo-Prefix.pch"; 435 | INFOPLIST_FILE = "SBTableLayoutDemo/SBTableLayoutDemo-Info.plist"; 436 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 437 | PRODUCT_NAME = "$(TARGET_NAME)"; 438 | WRAPPER_EXTENSION = app; 439 | }; 440 | name = Debug; 441 | }; 442 | F4C4204C183059C70054BE75 /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 446 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 447 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 448 | GCC_PREFIX_HEADER = "SBTableLayoutDemo/SBTableLayoutDemo-Prefix.pch"; 449 | INFOPLIST_FILE = "SBTableLayoutDemo/SBTableLayoutDemo-Info.plist"; 450 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | WRAPPER_EXTENSION = app; 453 | }; 454 | name = Release; 455 | }; 456 | F4C4204E183059C70054BE75 /* Debug */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 460 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SBTableLayoutDemo.app/SBTableLayoutDemo"; 461 | FRAMEWORK_SEARCH_PATHS = ( 462 | "$(SDKROOT)/Developer/Library/Frameworks", 463 | "$(inherited)", 464 | "$(DEVELOPER_FRAMEWORKS_DIR)", 465 | ); 466 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 467 | GCC_PREFIX_HEADER = "SBTableLayoutDemo/SBTableLayoutDemo-Prefix.pch"; 468 | GCC_PREPROCESSOR_DEFINITIONS = ( 469 | "DEBUG=1", 470 | "$(inherited)", 471 | ); 472 | INFOPLIST_FILE = "SBTableLayoutDemoTests/SBTableLayoutDemoTests-Info.plist"; 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | TEST_HOST = "$(BUNDLE_LOADER)"; 475 | WRAPPER_EXTENSION = xctest; 476 | }; 477 | name = Debug; 478 | }; 479 | F4C4204F183059C70054BE75 /* Release */ = { 480 | isa = XCBuildConfiguration; 481 | buildSettings = { 482 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 483 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SBTableLayoutDemo.app/SBTableLayoutDemo"; 484 | FRAMEWORK_SEARCH_PATHS = ( 485 | "$(SDKROOT)/Developer/Library/Frameworks", 486 | "$(inherited)", 487 | "$(DEVELOPER_FRAMEWORKS_DIR)", 488 | ); 489 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 490 | GCC_PREFIX_HEADER = "SBTableLayoutDemo/SBTableLayoutDemo-Prefix.pch"; 491 | INFOPLIST_FILE = "SBTableLayoutDemoTests/SBTableLayoutDemoTests-Info.plist"; 492 | PRODUCT_NAME = "$(TARGET_NAME)"; 493 | TEST_HOST = "$(BUNDLE_LOADER)"; 494 | WRAPPER_EXTENSION = xctest; 495 | }; 496 | name = Release; 497 | }; 498 | /* End XCBuildConfiguration section */ 499 | 500 | /* Begin XCConfigurationList section */ 501 | F4C42013183059C70054BE75 /* Build configuration list for PBXProject "SBTableLayoutDemo" */ = { 502 | isa = XCConfigurationList; 503 | buildConfigurations = ( 504 | F4C42048183059C70054BE75 /* Debug */, 505 | F4C42049183059C70054BE75 /* Release */, 506 | ); 507 | defaultConfigurationIsVisible = 0; 508 | defaultConfigurationName = Release; 509 | }; 510 | F4C4204A183059C70054BE75 /* Build configuration list for PBXNativeTarget "SBTableLayoutDemo" */ = { 511 | isa = XCConfigurationList; 512 | buildConfigurations = ( 513 | F4C4204B183059C70054BE75 /* Debug */, 514 | F4C4204C183059C70054BE75 /* Release */, 515 | ); 516 | defaultConfigurationIsVisible = 0; 517 | defaultConfigurationName = Release; 518 | }; 519 | F4C4204D183059C70054BE75 /* Build configuration list for PBXNativeTarget "SBTableLayoutDemoTests" */ = { 520 | isa = XCConfigurationList; 521 | buildConfigurations = ( 522 | F4C4204E183059C70054BE75 /* Debug */, 523 | F4C4204F183059C70054BE75 /* Release */, 524 | ); 525 | defaultConfigurationIsVisible = 0; 526 | defaultConfigurationName = Release; 527 | }; 528 | /* End XCConfigurationList section */ 529 | }; 530 | rootObject = F4C42010183059C70054BE75 /* Project object */; 531 | } 532 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/SBAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SBAppDelegate.h 3 | // SBTableLayoutDemo 4 | // 5 | // Created by Simon Blommegård on 2013-11-10. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SBAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/SBAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBAppDelegate.m 3 | // SBTableLayoutDemo 4 | // 5 | // Created by Simon Blommegård on 2013-11-10. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "SBAppDelegate.h" 10 | 11 | @implementation SBAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 14 | return YES; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/SBTableLayoutDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | se.simonb.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/SBTableLayoutDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/SBTableLayoutViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SBTableLayoutViewController.h 3 | // SBTableLayoutDemo 4 | // 5 | // Created by Simon Blommegård on 2013-11-10. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SBTableLayoutViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/SBTableLayoutViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBTableLayoutViewController.m 3 | // SBTableLayoutDemo 4 | // 5 | // Created by Simon Blommegård on 2013-11-10. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "SBTableLayoutViewController.h" 10 | #import "SBCollectionViewTableCell.h" 11 | #import "SBCollectionViewTableLayout.h" 12 | #import "SBCollectionViewTableSupplementaryView.h" 13 | #import "UIColor+SBCollectionViewTableLayoutColors.h" 14 | 15 | @interface SBTableLayoutViewController () 16 | @property (nonatomic, strong) UICollectionView *collectionView; 17 | @property (nonatomic, strong) SBCollectionViewTableLayout *layout; 18 | @property (nonatomic, strong) NSDictionary *sectionHeadersFooters; 19 | @end 20 | 21 | @implementation SBTableLayoutViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | 26 | [self setSectionHeadersFooters:@{@"Header":[SBCollectionViewTableSupplementaryView atteributedStringForKind:UICollectionElementKindSectionHeader text:@"Section Header"], 27 | @"Footer":[SBCollectionViewTableSupplementaryView atteributedStringForKind:UICollectionElementKindSectionFooter text:@"Section Footer"]}]; 28 | 29 | [self.view addSubview:self.collectionView]; 30 | } 31 | 32 | #pragma mark - 33 | 34 | - (UICollectionView *)collectionView { 35 | if (!_collectionView) { 36 | _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:self.layout]; 37 | [_collectionView setAutoresizingMask:(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth)]; 38 | [_collectionView setDataSource:self]; 39 | [_collectionView setDelegate:self]; 40 | [_collectionView setBackgroundColor:[UIColor sb_tableBackgroundColor]]; 41 | [_collectionView setAlwaysBounceVertical:YES]; 42 | 43 | if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { 44 | [_collectionView setContentInset:UIEdgeInsetsMake(20.f, 0.f, 49.f, 0.f)]; 45 | [_collectionView setScrollIndicatorInsets:UIEdgeInsetsMake(0.f, 0.f, 49.f, 0.f)]; 46 | } 47 | 48 | [_collectionView registerClass:[SBCollectionViewTableCell class] forCellWithReuseIdentifier:@"Cell"]; 49 | [_collectionView registerClass:[SBCollectionViewTableSupplementaryView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"Header"]; 50 | [_collectionView registerClass:[SBCollectionViewTableSupplementaryView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"Footer"]; 51 | } 52 | return _collectionView; 53 | } 54 | 55 | - (SBCollectionViewTableLayout *)layout { 56 | if (!_layout) { 57 | _layout = [SBCollectionViewTableLayout new]; 58 | [_layout setItemSize:CGSizeMake(CGRectGetWidth(self.view.bounds), 44.f)]; 59 | } 60 | return _layout; 61 | } 62 | 63 | #pragma mark UICollectionViewDataSource 64 | 65 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 66 | return 3; 67 | } 68 | 69 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 70 | return section+1; 71 | } 72 | 73 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 74 | SBCollectionViewTableCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath]; 75 | 76 | return cell; 77 | } 78 | 79 | - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 80 | if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { 81 | SBCollectionViewTableSupplementaryView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"Header" forIndexPath:indexPath]; 82 | [view.label setAttributedText:self.sectionHeadersFooters[@"Header"]]; 83 | 84 | return view; 85 | } else { 86 | SBCollectionViewTableSupplementaryView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"Footer" forIndexPath:indexPath]; 87 | [view.label setAttributedText:self.sectionHeadersFooters[@"Footer"]]; 88 | 89 | return view; 90 | } 91 | } 92 | 93 | #pragma mark - UICollectionViewDelegateFlowLayout 94 | 95 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { 96 | return [SBCollectionViewTableSupplementaryView sizeForWidth:CGRectGetWidth(collectionView.bounds) 97 | atteributedString:self.sectionHeadersFooters[@"Header"]]; 98 | } 99 | 100 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { 101 | return [SBCollectionViewTableSupplementaryView sizeForWidth:CGRectGetWidth(collectionView.bounds) 102 | atteributedString:self.sectionHeadersFooters[@"Footer"]]; 103 | } 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/SBTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SBTableViewController.h 3 | // SBTableLayoutDemo 4 | // 5 | // Created by Simon Blommegård on 2013-11-10. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SBTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/SBTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBTableViewController.m 3 | // SBTableLayoutDemo 4 | // 5 | // Created by Simon Blommegård on 2013-11-10. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import "SBTableViewController.h" 10 | 11 | @interface SBTableViewController () 12 | 13 | @end 14 | 15 | @implementation SBTableViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { 20 | [self.tableView setContentInset:UIEdgeInsetsMake(0.f, 0.f, 49.f, 0.f)]; 21 | [self.tableView setScrollIndicatorInsets:self.tableView.contentInset]; 22 | } 23 | } 24 | 25 | #pragma mark - UITableViewDelegate 26 | 27 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 28 | return 3; 29 | } 30 | 31 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 32 | return section+1; 33 | } 34 | 35 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 36 | static NSString *CellIdentifier = @"Cell"; 37 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier 38 | forIndexPath:indexPath]; 39 | 40 | return cell; 41 | } 42 | 43 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 44 | return @"Section Header"; 45 | } 46 | 47 | - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { 48 | return @"Section Footer"; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SBTableLayoutDemo 4 | // 5 | // Created by Simon Blommegård on 2013-11-10. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "SBAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SBAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemoTests/SBTableLayoutDemoTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | se.simonb.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemoTests/SBTableLayoutDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SBTableLayoutDemoTests.m 3 | // SBTableLayoutDemoTests 4 | // 5 | // Created by Simon Blommegård on 2013-11-10. 6 | // Copyright (c) 2013 Simon Blommegård. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SBTableLayoutDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation SBTableLayoutDemoTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /SBTableLayoutDemo/SBTableLayoutDemoTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------