├── .gitignore ├── A3GridTableView ├── A3GridTableView.h ├── A3GridTableView.m ├── A3GridTableViewCell.h └── A3GridTableViewCell.m ├── A3GridTableViewSample.xcodeproj └── project.pbxproj ├── A3GridTableViewSample ├── A3GridTableViewSample-Info.plist ├── A3GridTableViewSample-Prefix.pch ├── AppDelegate.h ├── AppDelegate.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── LaunchImage.launchimage │ │ ├── Contents.json │ │ ├── Default-568h@2x.png │ │ ├── Default.png │ │ └── Default@2x.png │ ├── cellBG-highlighted.imageset │ │ ├── Contents.json │ │ └── cellBG-highlighted.png │ └── cellBG-normal.imageset │ │ ├── Contents.json │ │ └── cellBG-normal.png ├── ViewController.h ├── ViewController.m ├── en.lproj │ ├── InfoPlist.strings │ └── ViewController.xib └── main.m ├── A3GridTableViewSampleIPad.m4v ├── A3GridTableViewSampleIPhone.m4v ├── LICENSE.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | -------------------------------------------------------------------------------- /A3GridTableView/A3GridTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // A3GridTableView.h 3 | // A3GridTableViewSample 4 | // 5 | // A3GridView for iOS 6 | // Created by Botond Kis on 28.09.12. 7 | // Copyright (c) 2012 aaa - All About Apps 8 | // All rights reserved. 9 | // 10 | // Redistribution and use in source and binary forms, with or without modification, 11 | // are permitted provided that the following conditions are met: 12 | // 13 | // - Redistributions of source code must retain the above copyright notice, this list 14 | // of conditions and the following disclaimer. 15 | // 16 | // - Redistributions in binary form must reproduce the above copyright notice, this list 17 | // of conditions and the following disclaimer in the documentation and/or other materials 18 | // provided with the distribution. 19 | // 20 | // - Neither the name of the "aaa - All About Apps" nor the names of its contributors may be used 21 | // to endorse or promote products derived from this software without specific prior written 22 | // permission. 23 | // 24 | // 25 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 27 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | // NO DOUGHNUTS WHERE HARMED DURING THE CODING OF THIS CLASS. BUT CHEESECAKES 36 | // WHERE. IF YOU READ THIS YOU ARE EITHER BORED OR A LAWYER. 37 | 38 | 39 | #import 40 | #import "A3GridTableViewCell.h" 41 | @class A3GridTableView; 42 | 43 | 44 | //========================================================================================== 45 | #pragma mark - Paging position enumeration 46 | //========================================================================================== 47 | typedef enum { 48 | A3GridTableViewCellAlignmentLeft, 49 | A3GridTableViewCellAlignmentCenter, 50 | A3GridTableViewCellAlignmentRight 51 | } A3GridTableViewCellAlignment; 52 | 53 | //========================================================================================== 54 | #pragma mark - DataSource for the gridTableView 55 | //========================================================================================== 56 | /** 57 | @brief The Controller of a A3GridTableView has to be its DataSource and implement the required methods to work. 58 | */ 59 | @protocol A3GridTableViewDataSource 60 | 61 | @required 62 | /** 63 | @param gridTableView The gridTableView which asks for the number of sections. 64 | @return Returns the GridTableView the number of sections. A section will be presented as a custom column in the GridTableView. 65 | */ 66 | - (NSInteger)numberOfSectionsInA3GridTableView:(A3GridTableView *) gridTableView; 67 | 68 | /** 69 | @param gridTableView The gridTableView which asks for the number of items in a section. 70 | @param section The section of the GridTableView for which the dataSource should return the number of rows. 71 | @return return the GridTableView the number of sections. A section will be presented as a custom column in the GridTableView. 72 | */ 73 | - (NSInteger)A3GridTableView:(A3GridTableView *) tableView numberOfRowsInSection:(NSInteger) section; 74 | 75 | /** 76 | @param gridTableView The gridTableView which asks for a cell. 77 | @param section The indexPath of the cell. 78 | @return return the GridTableView a A3GridTableViewCell for the cell at the indexPath. Must not be nil. 79 | */ 80 | - (A3GridTableViewCell *)A3GridTableView:(A3GridTableView *)gridTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; 81 | 82 | @optional 83 | /** 84 | @brief Called before the cell will be displayed or updated. Default is 44 points. 85 | @param gridTableView The gridTableView which asks for the Height for a cell. 86 | @param indexPath The indexPath of the cell 87 | @return return the height for the Cell at the indexPath. 88 | */ 89 | - (CGFloat)A3GridTableView:(A3GridTableView *) gridTableView heightForHeaders:(NSIndexPath *) indexPath; 90 | 91 | /** 92 | @param gridTableView The gridTableView which asks for a header. 93 | @param section The section of the header. 94 | @return return the GridTableView a A3GridTableViewCell as a Header. If nil or not implemented, there will be no header in the section. 95 | */ 96 | - (A3GridTableViewCell *)A3GridTableView:(A3GridTableView *) gridTableView headerForSection:(NSInteger) section; 97 | 98 | /** 99 | @param gridTableView The gridTableView which asks for the Height. 100 | @return return the Height for all Headers in the gridTableView. 101 | @brief Called once for all headers in reloadData(). Default is 44 points. 102 | */ 103 | - (CGFloat)heightForHeadersInA3GridTableView:(A3GridTableView *) gridTableView; 104 | 105 | /** 106 | @param gridTableView The gridTableView which asks for the width for a section. 107 | @return return the Width for the section. 108 | @brief Called once for all headers in reloadData(). Default is the Screenwidth. 109 | */ 110 | - (CGFloat)A3GridTableView:(A3GridTableView *) gridTableView widthForSection:(NSInteger) section; 111 | 112 | /** 113 | @param gridTableView The gridTableView which asks for the Height for a cell. 114 | @param indexPath The indexPath of the cell 115 | @return return the height for the Cell at the indexPath. 116 | @brief Called before the cell will be displayed or updated. Default is 44 points. 117 | */ 118 | - (CGFloat)A3GridTableView:(A3GridTableView *) gridTableView heightForRowAtIndexPath:(NSIndexPath *) indexPath; 119 | 120 | @end 121 | 122 | 123 | //========================================================================================== 124 | #pragma mark - Delegate for the gridTableView 125 | //========================================================================================== 126 | /* 127 | @brief The GridTableViewDelegate extends the UIScrollViewDelegate. The Controller which acts as a delegate for a GridTableView can implement methods similar to a UITableView. 128 | */ 129 | @protocol A3GridTableViewDelegate 130 | 131 | @optional 132 | // Header/Sections 133 | 134 | /** 135 | @param gridTableView The gridTableView which calls the delegate. 136 | @param section The index of the section which will be displayed. 137 | @brief Called before the section will be displayed. 138 | */ 139 | - (void) A3GridTableView:(A3GridTableView *)gridTableView willDisplaySection:(NSInteger) section; 140 | 141 | /** 142 | @param gridTableView The gridTableView which calls the delegate. 143 | @param section The index of the section which was selected. 144 | @brief Called when the section is selected. 145 | */ 146 | - (void) A3GridTableView:(A3GridTableView *)gridTableView didSelectHeaderAtSection:(NSInteger) section; 147 | 148 | 149 | // Cells 150 | 151 | /** 152 | @param gridTableView The gridTableView which calls the delegate. 153 | @param section The indexPath of the Cell which will be displayed. 154 | @brief Called before the Cell will be displayed. 155 | */ 156 | - (void) A3GridTableView:(A3GridTableView *)gridTableView willDisplayCellAtIndexPath:(NSIndexPath *) indexPath; 157 | 158 | /** 159 | @param gridTableView The gridTableView which calls the delegate. If not implemented, every cell is selectable. 160 | @param section The indexPath of the Cell which will be selected. 161 | @brief Called before the Cell is selected. 162 | @return Whether the cell is selectable or not 163 | */ 164 | - (BOOL) A3GridTableView:(A3GridTableView *)gridTableView canSelectCellAtIndexPath:(NSIndexPath *) indexPath; 165 | 166 | /** 167 | @param gridTableView The gridTableView which calls the delegate. 168 | @param section The indexPath of the Cell which was selected. 169 | @brief Called when the Cell is selected. 170 | */ 171 | - (void) A3GridTableView:(A3GridTableView *)gridTableView didSelectCellAtIndexPath:(NSIndexPath *) indexPath; 172 | 173 | /** 174 | @param gridTableView The gridTableView which calls the delegate. 175 | @param section The indexPath of the Cell which will be deselected. 176 | @brief Called before the Cell will be selected. 177 | */ 178 | - (void) A3GridTableView:(A3GridTableView *)gridTableView willDeselectCellAtIndexPath:(NSIndexPath *) indexPath; 179 | 180 | @end 181 | 182 | 183 | //========================================================================================== 184 | #pragma mark - Actual TableView 185 | //========================================================================================== 186 | /** 187 | @brief The GridTableView displays his Cells like a UITableView but in a grid based layout where the sections are represented as columns. 188 | */ 189 | @interface A3GridTableView : UIScrollView 190 | 191 | //=========================================== 192 | #pragma mark datasource and delegate 193 | //=========================================== 194 | // DataSource 195 | @property (nonatomic, weak) id dataSource; 196 | /** 197 | @brief Sets the DataSource of the GridTableView. By doing this, the GridTableView will automatically reload his data. 198 | @param aDataSource The ViewController which acts as the DataSource for the GridTableView. 199 | */ 200 | - (void)setDataSource:(id)aDataSource; 201 | 202 | // Delegate 203 | @property (nonatomic, weak) id delegate; 204 | /** 205 | @brief Sets the Delegate of the GridTableView. 206 | @param aDelegate The ViewController which acts as the Delegate for the GridTableView. 207 | */ 208 | - (void)setDelegate:(id)aDelegate; 209 | 210 | 211 | //=========================================== 212 | #pragma mark Update 213 | //=========================================== 214 | - (void)reloadData; 215 | 216 | - (void)reloadCellsWithViewAnimation:(BOOL)animated; 217 | 218 | //=========================================== 219 | #pragma mark Header 220 | //=========================================== 221 | - (A3GridTableViewCell *)dequeueReusableHeaderWithIdentifier:(NSString *)identifier; 222 | 223 | 224 | //=========================================== 225 | #pragma mark Cell 226 | //=========================================== 227 | - (A3GridTableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier; 228 | 229 | - (NSArray *)visibleCells; 230 | 231 | 232 | //=========================================== 233 | #pragma mark selections 234 | //=========================================== 235 | 236 | /** 237 | @brief return the indexPath of the currently selected cell. 238 | @return return nil if none item is selected. 239 | */ 240 | - (NSIndexPath *)indexPathForSelectedCell; 241 | 242 | /** 243 | @brief returns the indexPaths for all selected items. Empty array if no item is selected. 244 | @return returns nil if none item is selected. 245 | */ 246 | - (NSArray *)indexPathsForSelectedCells; 247 | 248 | /** 249 | @brief Selects the Cell at the given sindexPath. 250 | @param indexPath Index Path of the cell to be selected. 251 | @param animated Whether this should be animated or not. 252 | @param scrollPosition Vertical position of the cell. 253 | @param alignment Hoprizontal position of the cell. 254 | */ 255 | - (void)selectCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; 256 | 257 | /** 258 | @discussion Delects the Cell at the given indexPath. 259 | @param indexPath Index Path of the cell to be deselected. 260 | @param animated Whether this should be animated or not. 261 | */ 262 | - (void)deselectCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; 263 | 264 | /** 265 | @brief scrolls to the Cell at the given indexPath. 266 | @param indexPath IndexPath of the cell whcih will be scrolled to. 267 | @param scrollPosition Vertical position of the cell. 268 | @param alignment Hoprizontal position of the cell. 269 | @param animated Whether this should be animated or not. 270 | */ 271 | - (void)scrollToCellAtIndexPath:(NSIndexPath *)indexPath atCellAlignment:(A3GridTableViewCellAlignment)alignment atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated; 272 | 273 | 274 | /** 275 | @brief Enables/disables selection. Default is YES. 276 | */ 277 | @property (nonatomic, assign) BOOL allowsSelection; 278 | 279 | /** 280 | @brief Enables/disables multiple selection. Default is NO. 281 | */ 282 | @property (nonatomic, assign) BOOL allowsMultipleSelection; 283 | 284 | //=========================================== 285 | #pragma mark Index stuff 286 | //=========================================== 287 | /** 288 | @return Returns the indexPaths for the given Rect. 289 | */ 290 | - (NSArray *)indexPathsForRect:(CGRect)rect; 291 | 292 | /** 293 | @return Returns the indexPaths for the visible rect. 294 | */ 295 | - (NSArray *)indexPathsForVisibleRect; 296 | 297 | /** 298 | @return Returns the indexPaths of the sections for the given Rect. 299 | */ 300 | - (NSArray *)indexPathsForSectionsInRect:(CGRect)rect; 301 | 302 | /** 303 | @return Returns the indexPaths of the sections the visible Rect. 304 | */ 305 | - (NSArray *)indexPathsForVisibleSections; 306 | 307 | 308 | //=========================================== 309 | #pragma mark other 310 | //=========================================== 311 | - (CGRect)visibleRect; 312 | 313 | 314 | //=========================================== 315 | #pragma mark paging 316 | //=========================================== 317 | /** 318 | @brief Sets the position of the paging when paging is enabled.Default is A3GridTableViewPagingPositionCenter. 319 | */ 320 | @property(nonatomic, assign) A3GridTableViewCellAlignment pagingPosition; 321 | 322 | /** 323 | @brief A Boolean value that determines whether paging is enabled for the A3GridTableView. 324 | @discussion If the value of this property is YES, the scroll view alligns his section defined by pagingPosition when the user scrolls. The default value is NO. 325 | */ 326 | @property(nonatomic, getter = isGridTableViewPagingEnabled) BOOL gridTableViewPagingEnabled; 327 | - (BOOL)isGridTableViewPagingEnabled; 328 | 329 | @end 330 | -------------------------------------------------------------------------------- /A3GridTableView/A3GridTableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // A3GridTableView.m 3 | // A3GridTableViewSample 4 | // 5 | // A3GridView for iOS 6 | // Created by Botond Kis on 28.09.12. 7 | // Copyright (c) 2012 aaa - All About Apps 8 | // All rights reserved. 9 | // 10 | // Redistribution and use in source and binary forms, with or without modification, 11 | // are permitted provided that the following conditions are met: 12 | // 13 | // - Redistributions of source code must retain the above copyright notice, this list 14 | // of conditions and the following disclaimer. 15 | // 16 | // - Redistributions in binary form must reproduce the above copyright notice, this list 17 | // of conditions and the following disclaimer in the documentation and/or other materials 18 | // provided with the distribution. 19 | // 20 | // - Neither the name of the "aaa - All About Apps" nor the names of its contributors may be used 21 | // to endorse or promote products derived from this software without specific prior written 22 | // permission. 23 | // 24 | // 25 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 27 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | // NO DOUGHNUTS WHERE HARMED DURING THE CODING OF THIS CLASS. BUT CHEESECAKES 36 | // WHERE. IF YOU READ THIS YOU ARE EITHER BORED OR A LAWYER. 37 | 38 | 39 | #import "A3GridTableView.h" 40 | 41 | //=========================================================================================== 42 | #pragma mark - Default Values 43 | //=========================================================================================== 44 | 45 | //=========================================================================================== 46 | #pragma mark - Private Category 47 | //=========================================================================================== 48 | @interface A3GridTableView (){ 49 | 50 | //======================================================= 51 | // Datasource and delegate 52 | id __weak _dataSource; 53 | id __weak _delegateGridTableView; 54 | 55 | //======================================================= 56 | // visible Cells 57 | NSMutableSet *_visibleHeaders; 58 | NSMutableSet *_visibleCells; 59 | NSMutableArray *_visibleIndexPaths; 60 | NSMutableArray *_visibleSectionIndexPaths; 61 | 62 | // Containers for unused cells 63 | /** 64 | @brief Holds all unused cells in NSSets keyed by the reuseIdentifiers of the cells. Used by the dequeue() and _purge() methods. 65 | */ 66 | NSCache *_unusedHeaders; 67 | NSCache *_unusedCells; 68 | 69 | // selected Cells 70 | NSMutableArray *_selectedIndexPaths; 71 | 72 | //======================================================= 73 | // Layouting Information 74 | NSInteger numberOfSections; 75 | NSInteger *numberOfRowsInSection; 76 | 77 | /** 78 | @description Holds the widths of the sections. 79 | */ 80 | CGFloat *_sectionWidths; 81 | 82 | CGFloat *_sectionXOrigins; 83 | 84 | /** 85 | @description Holds the frames for all cells. The Frame at[section][row] 86 | */ 87 | CGRect **_cellFrames; 88 | 89 | /* custom paging*/ 90 | BOOL _gridTableViewPagingEnabled; 91 | 92 | 93 | //======================================================= 94 | // Touches 95 | BOOL _touchesAreDirty; 96 | 97 | //======================================================= 98 | // paging 99 | BOOL _deceleratingFromPaging; 100 | } 101 | 102 | // designated init 103 | - (void)_init; 104 | 105 | // Cell handling 106 | - (void)_purgeHeaderCell:(A3GridTableViewCell *)headerCell; 107 | - (void)_purgeCell:(A3GridTableViewCell *)cell; 108 | 109 | // layouting 110 | - (void)_layoutCells; 111 | - (void)_layoutHeaders; 112 | - (CGFloat)_heightForHeaders; 113 | 114 | /** 115 | @brief This method updates the Layout by building all frames and store them in cellFrames 116 | */ 117 | - (void)_updateCellFrames; 118 | 119 | // memory 120 | - (void)freeSectionWidths; 121 | - (void)freeCellFrames; 122 | - (void)freeSectionXOrigins; 123 | 124 | // paging 125 | - (void)_alignPageAnimated:(BOOL) animated; 126 | 127 | // alignment 128 | /** 129 | @brief This method returns the section for a given contentOffset 130 | @return The section for the contentOffset. Returns -1 if none found 131 | */ 132 | - (NSInteger)_sectionIndexForContentOffset:(CGPoint)contentOffset; 133 | 134 | // selection 135 | - (void)_deselectAllCells; 136 | - (void)_unhighlightAllCells; 137 | 138 | @end 139 | 140 | 141 | 142 | //=========================================================================================== 143 | #pragma mark - A3GridTableView 144 | //=========================================================================================== 145 | @implementation A3GridTableView 146 | @synthesize delegate = _delegateGridTableView; 147 | 148 | //=========================================================================================== 149 | #pragma mark - Constructors 150 | 151 | //====================================== 152 | // init called by all other init methods 153 | - (void)_init{ 154 | self.backgroundColor = [UIColor clearColor]; 155 | 156 | // visible Item Containers 157 | _visibleHeaders = [[NSMutableSet alloc] init]; 158 | _visibleCells = [[NSMutableSet alloc] init]; 159 | _visibleIndexPaths = [[NSMutableArray alloc] init]; 160 | _visibleSectionIndexPaths = [[NSMutableArray alloc] init]; 161 | 162 | // unused Item Containers 163 | _unusedHeaders = [[NSCache alloc] init]; 164 | _unusedCells = [[NSCache alloc] init]; 165 | 166 | // layout helper 167 | _sectionWidths = NULL; 168 | _sectionXOrigins = NULL; 169 | _cellFrames = NULL; 170 | 171 | numberOfSections = 0; 172 | numberOfRowsInSection = NULL; 173 | 174 | // Scrollview delegate 175 | [super setDelegate:self]; 176 | 177 | // paging 178 | _pagingPosition = A3GridTableViewCellAlignmentCenter; 179 | self.gridTableViewPagingEnabled = NO; 180 | 181 | // selection 182 | _allowsSelection = YES; 183 | _allowsMultipleSelection = NO; 184 | _selectedIndexPaths = [[NSMutableArray alloc] init]; 185 | } 186 | 187 | //====================================== 188 | // dealloc 189 | - (void)dealloc{ 190 | // layout helper 191 | [self freeSectionWidths]; 192 | [self freeSectionXOrigins]; 193 | [self freeCellFrames]; 194 | free(numberOfRowsInSection); 195 | } 196 | 197 | //====================================== 198 | // Initializers 199 | - (id)init{ 200 | self = [super init]; 201 | if (self) { 202 | [self _init]; 203 | } 204 | return self; 205 | } 206 | 207 | - (id)initWithFrame:(CGRect)frame{ 208 | self = [super initWithFrame:frame]; 209 | if (self) { 210 | [self _init]; 211 | } 212 | return self; 213 | } 214 | 215 | - (id)initWithCoder:(NSCoder *)aDecoder{ 216 | self = [super initWithCoder:aDecoder]; 217 | if (self) { 218 | [self _init]; 219 | } 220 | return self; 221 | } 222 | 223 | 224 | //=========================================================================================== 225 | #pragma mark - Message forwarding for scrollView Delegate 226 | 227 | /* called when not implementing a method asked by [respondsToSelector:]*/ 228 | - (void) forwardInvocation:(NSInvocation *)anInvocation{ 229 | 230 | // ask delegate if it's responding to selector 231 | if ([self.delegate respondsToSelector:[anInvocation selector]]) 232 | [anInvocation invokeWithTarget:self.delegate]; 233 | else 234 | [super forwardInvocation:anInvocation]; 235 | } 236 | 237 | /* ask the delegate if responds to a selector which we don't */ 238 | - (BOOL)respondsToSelector:(SEL)aSelector 239 | { 240 | if ( [super respondsToSelector:aSelector] ){ 241 | return YES; 242 | } 243 | else { 244 | // respond to selector if the delegate does 245 | if ([self.delegate respondsToSelector:aSelector]){ 246 | return YES; 247 | } 248 | } 249 | return NO; 250 | } 251 | 252 | - (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ 253 | 254 | // page if paging is enabled 255 | if (self.isGridTableViewPagingEnabled && !scrollView.tracking) { 256 | [self _alignPageAnimated:YES]; 257 | } 258 | 259 | // tell delegate, that this method was called 260 | if ([self.delegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) 261 | [self.delegate scrollViewDidEndDecelerating:scrollView]; 262 | } 263 | 264 | - (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ 265 | 266 | if (!decelerate) { 267 | // page if paging is enabled 268 | if (self.isGridTableViewPagingEnabled) { 269 | [self _alignPageAnimated:YES]; 270 | } 271 | } 272 | 273 | // tell delegate, that this method was called 274 | if ([self.delegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) 275 | [self.delegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; 276 | } 277 | 278 | //=========================================================================================== 279 | #pragma mark - Layout 280 | - (void)layoutSubviews{ 281 | [super layoutSubviews]; 282 | 283 | // cells 284 | [self _layoutCells]; 285 | 286 | // headers 287 | [self _layoutHeaders]; 288 | } 289 | 290 | 291 | - (void)_layoutCells{ 292 | 293 | @autoreleasepool { 294 | // get new visible indexPath 295 | NSArray *newVisibleIndexPaths = [self indexPathsForVisibleRect]; 296 | 297 | // create help array for enumarating 298 | NSArray *visibleCellsHelper = [NSArray arrayWithArray:[_visibleCells allObjects]]; 299 | 300 | // purge not visible cells 301 | for (A3GridTableViewCell *cell in visibleCellsHelper) { 302 | if (!CGRectIntersectsRect(cell.frame, [self visibleRect])) { 303 | 304 | // remove from visible cells 305 | [_visibleCells removeObject:cell]; 306 | 307 | // purge 308 | [self _purgeCell:cell]; 309 | } 310 | } 311 | 312 | // load new cells and add them as subview 313 | for (NSIndexPath *indexPath in newVisibleIndexPaths) { 314 | if (![_visibleIndexPaths containsObject:indexPath]) { 315 | // don't do an integrity check ([respondsToSelector:]) because the dataSource has to implement it. 316 | A3GridTableViewCell *newCell = [self.dataSource A3GridTableView:self cellForRowAtIndexPath:indexPath]; 317 | 318 | // set correct cellframe 319 | newCell.frame = _cellFrames[indexPath.section][indexPath.row]; 320 | newCell.indexPath = indexPath; 321 | 322 | // add cell as subview 323 | [self insertSubview:newCell atIndex:0]; 324 | 325 | // select / deselect cell 326 | if ([_selectedIndexPaths containsObject:newCell.indexPath]) { 327 | newCell.selected = YES; 328 | } 329 | else{ 330 | newCell.selected = NO; 331 | } 332 | 333 | // add to visible cells 334 | [_visibleCells addObject:newCell]; 335 | 336 | // call delegate if it responds 337 | if ([self.delegate respondsToSelector:@selector(A3GridTableView:willDisplayCellAtIndexPath:)]) { 338 | [self.delegate A3GridTableView:self willDisplayCellAtIndexPath:newCell.indexPath]; 339 | } 340 | } 341 | } 342 | 343 | // udpate visible paths 344 | [_visibleIndexPaths removeAllObjects]; 345 | [_visibleIndexPaths addObjectsFromArray:newVisibleIndexPaths]; 346 | } 347 | } 348 | 349 | 350 | - (void)_layoutHeaders{ 351 | // check if datasource implements the required method 352 | if (![self.dataSource respondsToSelector:@selector(A3GridTableView:headerForSection:)]) 353 | return; 354 | 355 | // get new visible indexPath 356 | NSArray *newVisibleIndexPaths = [self indexPathsForVisibleSections]; 357 | 358 | // create help array for enumarating 359 | NSArray *visibleHeadersHelper = [NSArray arrayWithArray:[_visibleHeaders allObjects]]; 360 | 361 | // purge not visible headers 362 | for (A3GridTableViewCell *header in visibleHeadersHelper) { 363 | CGRect helpHeaderFrame = [self visibleRect]; 364 | helpHeaderFrame.origin.x = header.frame.origin.x; 365 | helpHeaderFrame.size.width = header.frame.size.width; 366 | 367 | if (!CGRectIntersectsRect(helpHeaderFrame, [self visibleRect])) { 368 | 369 | // remove from visible cells 370 | [_visibleHeaders removeObject:header]; 371 | 372 | // purge 373 | [self _purgeHeaderCell:header]; 374 | } 375 | } 376 | 377 | 378 | // load new headers and add them as subview 379 | for (NSIndexPath *indexPath in newVisibleIndexPaths) { 380 | if (![_visibleSectionIndexPaths containsObject:indexPath]) { 381 | // don't do an integrity check ([respondsToSelector:]) because i do it at the top if this function 382 | A3GridTableViewCell *newHeader = [self.dataSource A3GridTableView:self headerForSection:indexPath.section]; 383 | newHeader.indexPath = indexPath; 384 | 385 | // add cell as subview 386 | [self addSubview:newHeader]; 387 | 388 | // set correct cellframe 389 | newHeader.frame = (CGRect){0, 0, _sectionWidths[indexPath.section], [self _heightForHeaders]}; 390 | 391 | // add to visible cells 392 | [_visibleHeaders addObject:newHeader]; 393 | 394 | // call delegate if it responds 395 | if ([self.delegate respondsToSelector:@selector(A3GridTableView:willDisplaySection:)]) { 396 | [self.delegate A3GridTableView:self willDisplaySection:indexPath.section]; 397 | } 398 | } 399 | } 400 | 401 | // allign headers 402 | for (A3GridTableViewCell *header in _visibleHeaders) { 403 | // set correct cellframe 404 | header.frame = (CGRect){_sectionXOrigins[header.indexPath.section], self.contentOffset.y, header.frame.size}; 405 | //[self bringSubviewToFront:header]; 406 | } 407 | 408 | 409 | // udpate visible paths 410 | [_visibleSectionIndexPaths removeAllObjects]; 411 | [_visibleSectionIndexPaths addObjectsFromArray:newVisibleIndexPaths]; 412 | } 413 | 414 | - (CGFloat)_heightForHeaders{ 415 | CGFloat heightForHeader = 0.0f; 416 | if ([self.dataSource respondsToSelector:@selector(A3GridTableView:headerForSection:)]) { 417 | // check header height and store the offset 418 | if ([self.dataSource respondsToSelector:@selector(heightForHeadersInA3GridTableView:)]) 419 | heightForHeader = [self.dataSource heightForHeadersInA3GridTableView:self]; 420 | else 421 | heightForHeader = 44.0f; 422 | } 423 | 424 | return heightForHeader; 425 | } 426 | 427 | - (void)_updateCellFrames{ 428 | // check if datasource is aviable 429 | if (!self.dataSource) { 430 | return; 431 | } 432 | 433 | /* 434 | There won't be many dataSource integrity checks (aka. [respondsToSelector:]) here, 435 | because most of the used methods are required by the dataSource! 436 | */ 437 | 438 | // whipe old info 439 | [self freeSectionWidths]; 440 | [self freeSectionXOrigins]; 441 | [self freeCellFrames]; 442 | free(numberOfRowsInSection); 443 | 444 | // get the number of sections 445 | numberOfSections = [self.dataSource numberOfSectionsInA3GridTableView:self]; 446 | numberOfRowsInSection = (NSInteger*)calloc(1, sizeof(NSInteger) * numberOfSections +1); 447 | 448 | // create new sectionWidth Array 449 | _sectionWidths = (CGFloat*)malloc(sizeof(CGFloat) * numberOfSections); 450 | _sectionXOrigins = (CGFloat*)malloc(sizeof(CGFloat) * numberOfSections); 451 | CGFloat originSectionX = 0.0f; 452 | 453 | // fill sections array 454 | for (int i = 0; i < numberOfSections; i++) { 455 | if ([self.dataSource respondsToSelector:@selector(A3GridTableView:widthForSection:)]){ 456 | // ask the datasource for the width 457 | _sectionWidths[i] = [self.dataSource A3GridTableView:self widthForSection:i]; 458 | } 459 | else{ // Use the screenwidth as default 460 | _sectionWidths[i] = self.frame.size.width; 461 | } 462 | 463 | // set section origin 464 | _sectionXOrigins[i] = originSectionX; 465 | originSectionX += _sectionWidths[i]; 466 | } 467 | 468 | 469 | // create new cellFrames Array and create correct Frames for the position 470 | _cellFrames = (CGRect**)calloc(1, sizeof(CGRect *) * numberOfSections + 1); 471 | 472 | // Contentsize 473 | CGSize newContentSize = CGSizeMake(0.0f, self.bounds.size.height+1.0f); 474 | 475 | // origins 476 | CGFloat originX = 0.0f; 477 | CGFloat originY = 0.0f; 478 | CGFloat offsetYForHeader = [self _heightForHeaders]; 479 | 480 | // build frame map 481 | for (int i = 0; i < numberOfSections; i++) { 482 | // get number of rows in section from datasource and alloc the array 483 | numberOfRowsInSection[i] = [self.dataSource A3GridTableView:self numberOfRowsInSection:i]; 484 | _cellFrames[i] = (CGRect*)malloc(sizeof(CGRect) * numberOfRowsInSection[i]); 485 | 486 | // sizes 487 | CGFloat width = _sectionWidths[i]; 488 | CGFloat height = 0.0f; 489 | 490 | // build frames for that collumn 491 | for (int j = 0; j < numberOfRowsInSection[i]; j++) { 492 | 493 | // ask the datasource for the cell height 494 | if ([self.dataSource respondsToSelector:@selector(A3GridTableView:heightForRowAtIndexPath:)]) 495 | height = [self.dataSource A3GridTableView:self heightForRowAtIndexPath:[NSIndexPath indexPathForRow:j inSection:i]]; 496 | else 497 | // default ist 44 points 498 | height = 44.0f; 499 | 500 | // set the frame 501 | _cellFrames[i][j] = (CGRect){originX, originY+offsetYForHeader, width, height}; 502 | 503 | // update originY 504 | originY += height; 505 | } 506 | 507 | // update contentsize 508 | newContentSize.width += width; 509 | newContentSize.height = MAX(newContentSize.height, originY + offsetYForHeader); 510 | 511 | // update originX and Y 512 | originX += width; 513 | originY = 0.0f; 514 | } 515 | 516 | // set contentsize 517 | self.contentSize = newContentSize; 518 | } 519 | 520 | 521 | //================================ 522 | #pragma mark Paging 523 | 524 | - (void)setGridTableViewPagingEnabled:(BOOL)enabled{ 525 | _gridTableViewPagingEnabled = enabled; 526 | } 527 | 528 | - (BOOL)isGridTableViewPagingEnabled{ 529 | return _gridTableViewPagingEnabled; 530 | } 531 | 532 | 533 | // Disable original scrollview paging 534 | - (BOOL)isPagingEnabled{ 535 | return NO; 536 | } 537 | - (void)setPagingEnabled:(BOOL)enabled{ 538 | [super setPagingEnabled:NO]; 539 | } 540 | // end disable 541 | 542 | - (void)_alignPageAnimated:(BOOL) animated{ 543 | 544 | // set info flag 545 | _deceleratingFromPaging = YES; 546 | 547 | // get the correct section 548 | CGPoint offsetForSection = self.contentOffset; 549 | 550 | switch (self.pagingPosition) { 551 | case A3GridTableViewCellAlignmentCenter: 552 | offsetForSection.x += self.frame.size.width/2.0f; 553 | break; 554 | case A3GridTableViewCellAlignmentRight: 555 | offsetForSection.x += self.frame.size.width-1; 556 | break; 557 | case A3GridTableViewCellAlignmentLeft: 558 | offsetForSection.x += 1; 559 | break; 560 | 561 | default: 562 | break; 563 | } 564 | 565 | // get item for offset 566 | int indexOfCell = [self _sectionIndexForContentOffset:offsetForSection]; 567 | 568 | // don't do anything when there is no item 569 | if (indexOfCell < 0) 570 | return; 571 | 572 | CGPoint newOffset = self.contentOffset; 573 | CGFloat pagingPositionOffset = 0.0f; 574 | 575 | 576 | switch (self.pagingPosition) { 577 | case A3GridTableViewCellAlignmentCenter: 578 | pagingPositionOffset = -self.frame.size.width/2.0f + _sectionWidths[indexOfCell]/2.0f; 579 | break; 580 | case A3GridTableViewCellAlignmentRight: 581 | pagingPositionOffset = -self.frame.size.width + _sectionWidths[indexOfCell]; 582 | break; 583 | 584 | case A3GridTableViewCellAlignmentLeft: 585 | default: 586 | pagingPositionOffset = 0.0f; 587 | break; 588 | } 589 | 590 | newOffset.x = _sectionXOrigins[indexOfCell] + pagingPositionOffset; 591 | newOffset.x = MAX(0.0f, newOffset.x); 592 | newOffset.x = MIN(newOffset.x, self.contentSize.width-self.frame.size.width); 593 | 594 | //[self setContentOffset:newOffset animated:animated]; 595 | if (animated) { 596 | [UIView animateWithDuration:0.3 597 | animations:^{ 598 | self.contentOffset = newOffset; 599 | } 600 | completion:^(BOOL finished) { 601 | 602 | _deceleratingFromPaging = NO; 603 | 604 | // call delegate 605 | if ([self.delegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) 606 | [self.delegate scrollViewDidEndDecelerating:self]; 607 | } 608 | ]; 609 | } 610 | else{ 611 | self.contentOffset = newOffset; 612 | _deceleratingFromPaging = NO; 613 | } 614 | } 615 | 616 | //=========================================================================================== 617 | #pragma mark - Reload 618 | 619 | - (void)reloadData{ 620 | 621 | // purge headers 622 | for (A3GridTableViewCell *headerCell in _visibleHeaders) { 623 | [self _purgeHeaderCell:headerCell]; 624 | } 625 | 626 | // purge cells 627 | for (A3GridTableViewCell *cell in [self visibleCells]) { 628 | [self _purgeCell:cell]; 629 | } 630 | 631 | // reset stuff 632 | [_visibleIndexPaths removeAllObjects]; 633 | [_visibleSectionIndexPaths removeAllObjects]; 634 | [_visibleHeaders removeAllObjects]; 635 | [_visibleCells removeAllObjects]; 636 | 637 | // relayout 638 | [self _updateCellFrames]; 639 | 640 | // cells 641 | [self _layoutCells]; 642 | 643 | // headers 644 | [self _layoutHeaders]; 645 | } 646 | 647 | 648 | - (void)reloadCellsWithViewAnimation:(BOOL)animated{ 649 | // relayout 650 | [self _updateCellFrames]; 651 | 652 | // change their frames 653 | for (A3GridTableViewCell *cell in [self visibleCells]) { 654 | if (animated) { 655 | [UIView animateWithDuration:0.4 animations:^{ 656 | cell.frame = _cellFrames[cell.indexPath.section][cell.indexPath.row]; 657 | }]; 658 | } 659 | else{ 660 | cell.frame = _cellFrames[cell.indexPath.section][cell.indexPath.row]; 661 | } 662 | } 663 | } 664 | 665 | 666 | //=========================================================================================== 667 | #pragma mark - datasource and delegate 668 | // DataSource 669 | - (void)setDataSource:(id)aDataSource{ 670 | 671 | // ignore if both sources are equal 672 | if (aDataSource == _dataSource) 673 | return; 674 | 675 | // memory stuff 676 | _dataSource = aDataSource; 677 | 678 | // reload data 679 | [self reloadData]; 680 | } 681 | 682 | 683 | // Delegate 684 | - (void)setDelegate:(id)aDelegate{ 685 | 686 | // memory stuff 687 | _delegateGridTableView = aDelegate; 688 | 689 | // set scrollviewDelegate 690 | [super setDelegate:nil]; 691 | [super setDelegate:self]; 692 | } 693 | 694 | 695 | //=========================================================================================== 696 | #pragma mark - Touches 697 | 698 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 699 | // call super 700 | [super touchesBegan:touches withEvent:event]; 701 | 702 | // reset moved 703 | _touchesAreDirty = NO; 704 | 705 | // return if selection is disabled 706 | if (!self.allowsSelection && !self.allowsMultipleSelection) 707 | return; 708 | 709 | // get the touch 710 | UITouch *touch = [touches anyObject]; 711 | CGPoint touchPoint = [touch locationInView:self]; 712 | 713 | // iterate through visible headers 714 | for (A3GridTableViewCell *header in _visibleHeaders) { 715 | 716 | // if touch is inside cell highlight it and break 717 | if (CGRectContainsPoint(header.frame, touchPoint)) { 718 | 719 | // highlighted cell 720 | [header setHighlighted:YES animated:YES]; 721 | 722 | return; 723 | } 724 | } 725 | 726 | 727 | // iterate through visible cells 728 | for (A3GridTableViewCell *cell in [self visibleCells]) { 729 | 730 | // Ask delegate if cell is selectable. 731 | if ([self.delegate respondsToSelector:@selector(A3GridTableView:canSelectCellAtIndexPath:)]) { 732 | BOOL canSelectCell = [self.delegate A3GridTableView:self canSelectCellAtIndexPath:cell.indexPath]; 733 | 734 | // When not break loop. 735 | if (!canSelectCell) break; 736 | } 737 | 738 | // if touch is inside cell highlight it and break 739 | if (CGRectContainsPoint(cell.frame, touchPoint)) { 740 | 741 | // highlighted cell 742 | [cell setHighlighted:YES animated:YES]; 743 | 744 | // ignore others when header was selected 745 | break; 746 | } 747 | } 748 | } 749 | 750 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 751 | // call super 752 | [super touchesMoved:touches withEvent:event]; 753 | 754 | // deselect all 755 | if (!_touchesAreDirty) { 756 | [self _unhighlightAllCells]; 757 | _touchesAreDirty = YES; 758 | } 759 | } 760 | 761 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{ 762 | // call super 763 | [super touchesCancelled:touches withEvent:event]; 764 | 765 | // deselect all 766 | if (!_touchesAreDirty) { 767 | [self _unhighlightAllCells]; 768 | _touchesAreDirty = YES; 769 | } 770 | } 771 | 772 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ 773 | // call super 774 | [super touchesEnded:touches withEvent:event]; 775 | 776 | // unhighlight all cells 777 | [self _unhighlightAllCells]; 778 | 779 | // return if selection is disabled 780 | if (!self.allowsSelection && !self.allowsMultipleSelection) 781 | return; 782 | 783 | // get the touch 784 | UITouch *touch = [touches anyObject]; 785 | CGPoint touchPoint = [touch locationInView:self]; 786 | 787 | 788 | // iterate through visible headers 789 | for (A3GridTableViewCell *header in _visibleHeaders) { 790 | 791 | if (CGRectContainsPoint(header.frame, touchPoint)){ 792 | // call delegate if it responds 793 | if ([self.delegate respondsToSelector:@selector(A3GridTableView:didSelectHeaderAtSection:)]) { 794 | [self.delegate A3GridTableView:self didSelectHeaderAtSection:header.indexPath.section]; 795 | } 796 | 797 | // ignore others when header was selected 798 | return; 799 | } 800 | } 801 | 802 | // iterate through visible cells 803 | for (A3GridTableViewCell *cell in [self visibleCells]) { 804 | 805 | // Ask delegate if cell is selectable. 806 | if ([self.delegate respondsToSelector:@selector(A3GridTableView:canSelectCellAtIndexPath:)]) { 807 | BOOL canSelectCell = [self.delegate A3GridTableView:self canSelectCellAtIndexPath:cell.indexPath]; 808 | 809 | // When not, ignore touches 810 | if (!canSelectCell) continue; 811 | } 812 | 813 | if (CGRectContainsPoint(cell.frame, touchPoint)) { 814 | // deselect cell 815 | if ([_selectedIndexPaths containsObject:cell.indexPath]) { 816 | [self deselectCellAtIndexPath:cell.indexPath animated:YES]; 817 | } 818 | // Select cell 819 | else{ 820 | [self selectCellAtIndexPath:cell.indexPath animated:YES]; 821 | } 822 | } 823 | else{ 824 | // deselect not touched cell if multiple selection isn't enabled 825 | if (!self.allowsMultipleSelection && [_selectedIndexPaths containsObject:cell.indexPath]) { 826 | [self deselectCellAtIndexPath:cell.indexPath animated:YES]; 827 | } 828 | } 829 | } 830 | } 831 | 832 | //=========================================================================================== 833 | #pragma mark - Cell Handling 834 | 835 | //====================== 836 | #pragma mark Dequeue 837 | ///////////////// 838 | // Dequeue Header 839 | - (A3GridTableViewCell *)dequeueReusableHeaderWithIdentifier:(NSString *)identifier{ 840 | // header to dequeue 841 | A3GridTableViewCell *headerToDequeue = nil; 842 | 843 | // get a Set of unusedHeaders for the reuseIdentifier 844 | NSMutableSet *setFromReuseIdentifier = [_unusedHeaders objectForKey:identifier]; 845 | 846 | // get headerCell from set if set exists 847 | if (setFromReuseIdentifier) { 848 | headerToDequeue = [setFromReuseIdentifier anyObject]; 849 | if (headerToDequeue) 850 | [setFromReuseIdentifier removeObject:headerToDequeue]; 851 | } 852 | 853 | // prepare cell for reuse 854 | [headerToDequeue prepareForReuse]; 855 | 856 | // return dequeued header 857 | return headerToDequeue; 858 | } 859 | 860 | /////////////// 861 | // Dequeue Cell 862 | - (A3GridTableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier{ 863 | 864 | // cell to dequeue 865 | A3GridTableViewCell *cellToDequeue = nil; 866 | 867 | // get a Set of unusedCell for the reuseIdentifier 868 | NSMutableSet *setFromReuseIdentifier = [_unusedCells objectForKey:identifier]; 869 | 870 | // get cell from set if set exists 871 | if (setFromReuseIdentifier) { 872 | cellToDequeue = [setFromReuseIdentifier anyObject]; 873 | if (cellToDequeue) 874 | [setFromReuseIdentifier removeObject:cellToDequeue]; 875 | } 876 | 877 | // prepare cell for reuse 878 | [cellToDequeue prepareForReuse]; 879 | 880 | // return dequeued cell 881 | return cellToDequeue; 882 | } 883 | 884 | 885 | //====================== 886 | #pragma mark Purging 887 | /////////////// 888 | // Purge Header 889 | - (void)_purgeHeaderCell:(A3GridTableViewCell *)headerCell{ 890 | // remove headerCell from view 891 | [headerCell removeFromSuperview]; 892 | 893 | // reset indexpath 894 | headerCell.indexPath = nil; 895 | 896 | // don't cache if there is no reuse identifier 897 | if (headerCell.reuseIdentifier) { 898 | 899 | // get Set for reuse identifier 900 | NSMutableSet *setFromIdentifier = [_unusedHeaders objectForKey:headerCell.reuseIdentifier]; 901 | 902 | // make new set if there is none 903 | if (!setFromIdentifier) { 904 | // create new set 905 | setFromIdentifier = [[NSMutableSet alloc] initWithCapacity:16]; 906 | 907 | // add to unused headers 908 | [_unusedHeaders setObject:setFromIdentifier forKey:headerCell.reuseIdentifier]; 909 | } 910 | 911 | // add headerCell to set and clean up 912 | [setFromIdentifier addObject:headerCell]; 913 | 914 | // clean 915 | } 916 | } 917 | 918 | ///////////// 919 | // Purge Cell 920 | - (void)_purgeCell:(A3GridTableViewCell *)cell{ 921 | // remove headerCell from view 922 | [cell removeFromSuperview]; 923 | 924 | // reset indexpath 925 | cell.indexPath = nil; 926 | 927 | // don't cache if there is no reuse identifier 928 | if (cell.reuseIdentifier) { 929 | 930 | // get Set for reuse identifier 931 | NSMutableSet *setFromIdentifier = [_unusedCells objectForKey:cell.reuseIdentifier]; 932 | 933 | // make new set if there is none 934 | if (!setFromIdentifier) { 935 | // create new set 936 | setFromIdentifier = [[NSMutableSet alloc] initWithCapacity:32]; 937 | 938 | // add to unused headers 939 | [_unusedCells setObject:setFromIdentifier forKey:cell.reuseIdentifier]; 940 | } 941 | 942 | // add cell to set and clean up 943 | [setFromIdentifier addObject:cell]; 944 | 945 | // clean 946 | } 947 | } 948 | 949 | //=========================================================================================== 950 | #pragma mark - memory 951 | - (void)freeSectionWidths{ 952 | free(_sectionWidths); 953 | _sectionWidths = NULL; 954 | } 955 | 956 | 957 | - (void)freeSectionXOrigins{ 958 | free(_sectionXOrigins); 959 | _sectionXOrigins = NULL; 960 | } 961 | 962 | - (void)freeCellFrames{ 963 | if (_cellFrames) { 964 | for (int i = 0; _cellFrames[i]; i++) { 965 | free(_cellFrames[i]); 966 | _cellFrames[i] = NULL; 967 | } 968 | } 969 | free(_cellFrames); 970 | _cellFrames = NULL; 971 | } 972 | 973 | 974 | 975 | //=========================================================================================== 976 | #pragma mark - selections 977 | 978 | - (NSIndexPath *)indexPathForSelectedCell{ 979 | NSIndexPath *selectedIndexPath = nil; 980 | 981 | if ([_selectedIndexPaths count] > 0) { 982 | selectedIndexPath = _selectedIndexPaths[0]; 983 | } 984 | 985 | return selectedIndexPath; 986 | } 987 | 988 | - (NSArray *)indexPathsForSelectedCells{ 989 | return _selectedIndexPaths; 990 | } 991 | 992 | - (void)selectCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated{ 993 | 994 | // add index to selected indices 995 | [_selectedIndexPaths addObject:indexPath]; 996 | 997 | // set cell selection 998 | for (A3GridTableViewCell *cell in [self visibleCells]) { 999 | // select / deselect cell 1000 | if ([indexPath isEqual: cell.indexPath]) { 1001 | [cell setSelected:YES animated:animated]; 1002 | break; 1003 | } 1004 | } 1005 | 1006 | // call delegate if it responds 1007 | if ([self.delegate respondsToSelector:@selector(A3GridTableView:didSelectCellAtIndexPath:)]) { 1008 | [self.delegate A3GridTableView:self didSelectCellAtIndexPath:indexPath]; 1009 | } 1010 | 1011 | } 1012 | 1013 | - (void)deselectCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated{ 1014 | 1015 | // remove indexpath from selected indices 1016 | [_selectedIndexPaths removeObject:indexPath]; 1017 | 1018 | // set cell selection 1019 | for (A3GridTableViewCell *cell in [self visibleCells]) { 1020 | // select / deselect cell 1021 | if ([indexPath isEqual: cell.indexPath]) { 1022 | [cell setSelected:NO animated:animated]; 1023 | break; 1024 | } 1025 | } 1026 | 1027 | // call delegate if it responds 1028 | if ([self.delegate respondsToSelector:@selector(A3GridTableView:willDeselectCellAtIndexPath:)]) { 1029 | [self.delegate A3GridTableView:self willDeselectCellAtIndexPath:indexPath]; 1030 | } 1031 | } 1032 | 1033 | - (void)scrollToCellAtIndexPath:(NSIndexPath *)indexPath atCellAlignment:(A3GridTableViewCellAlignment)alignment atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated{ 1034 | // get frame of cell at the index 1035 | CGRect rectOfCellAtIndexPath = _cellFrames[indexPath.section][indexPath.row]; 1036 | CGPoint newContentOffset = rectOfCellAtIndexPath.origin; 1037 | 1038 | // align horizontaly 1039 | switch (alignment) { 1040 | case A3GridTableViewCellAlignmentCenter: 1041 | newContentOffset.x = -self.frame.size.width/2.0f + rectOfCellAtIndexPath.size.width/2.0f; 1042 | break; 1043 | case A3GridTableViewCellAlignmentRight: 1044 | newContentOffset.x = -self.frame.size.width + rectOfCellAtIndexPath.size.width; 1045 | break; 1046 | case A3GridTableViewCellAlignmentLeft: 1047 | default: 1048 | break; 1049 | } 1050 | 1051 | // align vertically 1052 | switch (scrollPosition) { 1053 | case UITableViewScrollPositionMiddle: 1054 | newContentOffset.y = -self.frame.size.width/2.0 + rectOfCellAtIndexPath.size.width/2.0; 1055 | break; 1056 | case UITableViewScrollPositionBottom: 1057 | newContentOffset.y = -self.frame.size.width + rectOfCellAtIndexPath.size.width; 1058 | break; 1059 | case UITableViewScrollPositionTop: 1060 | default: 1061 | break; 1062 | } 1063 | 1064 | // set content offset 1065 | [self setContentOffset:newContentOffset animated:animated]; 1066 | } 1067 | 1068 | - (void)_deselectAllCells{ 1069 | for (A3GridTableViewCell *cell in [self visibleCells]) { 1070 | // unselect 1071 | cell.selected = NO; 1072 | } 1073 | } 1074 | 1075 | - (void)_unhighlightAllCells{ 1076 | // header 1077 | for (A3GridTableViewCell *header in _visibleHeaders) { 1078 | // unhighlight 1079 | [header setHighlighted:NO animated:YES]; 1080 | } 1081 | 1082 | // cells 1083 | for (A3GridTableViewCell *cell in [self visibleCells]) { 1084 | // unhighlight 1085 | [cell setHighlighted:NO animated:YES]; 1086 | } 1087 | } 1088 | 1089 | //=========================================================================================== 1090 | #pragma mark - Index stuff 1091 | 1092 | - (NSArray *)indexPathsForRect:(CGRect)rect{ 1093 | 1094 | // initialize return array 1095 | NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; 1096 | 1097 | // iterate through all cells 1098 | for (int i = 0; i < numberOfSections; i++) { 1099 | for (int j = 0; j < numberOfRowsInSection[i]; j++) { 1100 | 1101 | // get frame of cell at the indexpath 1102 | CGRect cellFrame = _cellFrames[i][j]; 1103 | 1104 | // if frame of cell is inside the visible frame of 1105 | // the scrollview then add it to the indexPath array 1106 | if (CGRectIntersectsRect(cellFrame, rect)) { 1107 | [indexPaths addObject:[NSIndexPath indexPathForRow:j inSection:i]]; 1108 | } 1109 | } 1110 | } 1111 | 1112 | return indexPaths; 1113 | } 1114 | 1115 | - (NSArray *)indexPathsForVisibleRect{ 1116 | return [self indexPathsForRect:[self visibleRect]]; 1117 | } 1118 | 1119 | - (NSArray *)indexPathsForSectionsInRect:(CGRect)rect{ 1120 | // initialize return array 1121 | NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; 1122 | 1123 | // iterate through all sections 1124 | CGFloat posX = 0.0f; 1125 | 1126 | for (int i = 0; i < numberOfSections; i++) { 1127 | 1128 | // Build rect for section 1129 | CGRect rectOfsection = rect; 1130 | rectOfsection.origin.x = posX; 1131 | rectOfsection.size.width = _sectionWidths[i]; 1132 | 1133 | // add to indexpaths if it contains it 1134 | if (CGRectIntersectsRect(rect, rectOfsection)) { 1135 | [indexPaths addObject:[NSIndexPath indexPathForRow:0 inSection:i]]; 1136 | } 1137 | 1138 | // update posx 1139 | posX += _sectionWidths[i]; 1140 | } 1141 | 1142 | return indexPaths; 1143 | } 1144 | 1145 | - (NSArray *)indexPathsForVisibleSections{ 1146 | return [self indexPathsForSectionsInRect:[self visibleRect]]; 1147 | } 1148 | 1149 | // alignment 1150 | - (NSInteger)_sectionIndexForContentOffset:(CGPoint)contentOffset{ 1151 | int section = -1; 1152 | CGFloat minDeltaX = -1.0; 1153 | 1154 | for (int i = 0 ; i < numberOfSections; i++) { 1155 | 1156 | CGFloat deltaX = fabs(contentOffset.x - _sectionXOrigins[i] - _sectionWidths[i]/2.0f); 1157 | 1158 | if (deltaX < minDeltaX || section < 0) { 1159 | section = i; 1160 | minDeltaX = deltaX; 1161 | } 1162 | } 1163 | 1164 | return section; 1165 | } 1166 | 1167 | 1168 | //=========================================================================================== 1169 | #pragma mark - Properties 1170 | 1171 | - (NSArray *)visibleCells{ 1172 | return [_visibleCells allObjects]; 1173 | } 1174 | 1175 | - (BOOL)isDecelerating{ 1176 | BOOL superDecel = [super isDecelerating]; 1177 | return superDecel || _deceleratingFromPaging; 1178 | } 1179 | 1180 | //=========================================================================================== 1181 | #pragma mark - helper 1182 | 1183 | - (CGRect)visibleRect{ 1184 | // calc visible Rect 1185 | CGRect visibleRect = self.bounds; 1186 | visibleRect.origin = self.contentOffset; 1187 | 1188 | return visibleRect; 1189 | } 1190 | 1191 | @end 1192 | -------------------------------------------------------------------------------- /A3GridTableView/A3GridTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // A3GridTableViewCell.h 3 | // A3GridTableViewSample 4 | // 5 | // A3GridView for iOS 6 | // Created by Botond Kis on 28.09.12. 7 | // Copyright (c) 2012 aaa - All About Apps 8 | // All rights reserved. 9 | // 10 | // Redistribution and use in source and binary forms, with or without modification, 11 | // are permitted provided that the following conditions are met: 12 | // 13 | // - Redistributions of source code must retain the above copyright notice, this list 14 | // of conditions and the following disclaimer. 15 | // 16 | // - Redistributions in binary form must reproduce the above copyright notice, this list 17 | // of conditions and the following disclaimer in the documentation and/or other materials 18 | // provided with the distribution. 19 | // 20 | // - Neither the name of the "aaa - All About Apps" nor the names of its contributors may be used 21 | // to endorse or promote products derived from this software without specific prior written 22 | // permission. 23 | // 24 | // 25 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 27 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | // NO DOUGHNUTS WHERE HARMED DURING THE CODING OF THIS CLASS. BUT CHEESECAKES 36 | // WHERE. IF YOU READ THIS YOU ARE EITHER BORED OR A LAWYER. 37 | 38 | 39 | #import 40 | 41 | @interface A3GridTableViewCell : UIView 42 | 43 | /** 44 | @Description: Designated initializer. 45 | @param: reuseIdentifier If the cell can be reused, you must pass in a reuse identifier. You should use the same reuse identifier for all cells of the same form. 46 | */ 47 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier; 48 | 49 | //====================================================================== 50 | #pragma mark - Views 51 | /** 52 | @description: The default background which is visible. 53 | */ 54 | @property (nonatomic, strong) UIView *backgroundView; 55 | 56 | /** 57 | @description: The contenView holds all subviews of the cell. Use this View if you wan't to customize (add subviews) to the cell, rather than manipulating directly the cell. 58 | */ 59 | @property (nonatomic, strong) UIView *contentView; 60 | 61 | /** 62 | @description: The selectedBackgroundView is visible when the cell is selected. It is shown above the backgroundView but below the contentView. 63 | */ 64 | @property (nonatomic, strong) UIView *selectedBackgroundView; 65 | 66 | /** 67 | @description: The highlightedBackgroundView is visible when the cell is highlighted. It is shown above the backgroundView but below the contentView. 68 | */ 69 | @property (nonatomic, strong) UIView *highlightedBackgroundView; 70 | 71 | /** 72 | @description: The standard titleLabel. You can set it it nil if you don't need it. 73 | */ 74 | @property (nonatomic, strong) UILabel *titleLabel; 75 | 76 | 77 | //====================================================================== 78 | #pragma mark - Information 79 | 80 | /** 81 | @description: A string used to identify a cell that is reusable. 82 | */ 83 | @property (nonatomic, strong) NSString *reuseIdentifier; 84 | 85 | /** 86 | @description: If the cell is reusable (has a reuse identifier), this is called just before the cell is returned from the table view method [dequeueReusableCellWithIdentifier:]. 87 | */ 88 | - (void)prepareForReuse; 89 | 90 | 91 | /** 92 | @description: The indexpath of the cell when it is visible. If the cell is not visible, the value is invalid and should not be trusted. 93 | */ 94 | @property (nonatomic, strong) NSIndexPath *indexPath; 95 | 96 | 97 | 98 | /** 99 | @description: Set selected state (title, image, background). default is NO. animated is NO 100 | */ 101 | @property(nonatomic,getter=isSelected) BOOL selected; 102 | 103 | /** 104 | @description: Animate between regular and selected state 105 | */ 106 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated; 107 | 108 | 109 | 110 | /** 111 | @description: Set highlighted state (title, image, background). default is NO. animated is NO 112 | */ 113 | @property(nonatomic,getter=isHighlighted) BOOL highlighted; 114 | 115 | /** 116 | @description: Animate between regular and highlighted state 117 | */ 118 | - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated; 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /A3GridTableView/A3GridTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // A3GridTableViewCell.m 3 | // A3GridTableViewSample 4 | // 5 | // A3GridView for iOS 6 | // Created by Botond Kis on 28.09.12. 7 | // Copyright (c) 2012 aaa - All About Apps 8 | // All rights reserved. 9 | // 10 | // Redistribution and use in source and binary forms, with or without modification, 11 | // are permitted provided that the following conditions are met: 12 | // 13 | // - Redistributions of source code must retain the above copyright notice, this list 14 | // of conditions and the following disclaimer. 15 | // 16 | // - Redistributions in binary form must reproduce the above copyright notice, this list 17 | // of conditions and the following disclaimer in the documentation and/or other materials 18 | // provided with the distribution. 19 | // 20 | // - Neither the name of the "aaa - All About Apps" nor the names of its contributors may be used 21 | // to endorse or promote products derived from this software without specific prior written 22 | // permission. 23 | // 24 | // 25 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 27 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 29 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | // NO DOUGHNUTS WHERE HARMED DURING THE CODING OF THIS CLASS. BUT CHEESECAKES 36 | // WHERE. IF YOU READ THIS YOU ARE EITHER BORED OR A LAWYER. 37 | 38 | 39 | #import "A3GridTableViewCell.h" 40 | 41 | @implementation A3GridTableViewCell 42 | 43 | //=========================================================================================== 44 | #pragma mark - Memory 45 | 46 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier{ 47 | self = [super init]; 48 | if (self) { 49 | // Set the reuseIdentifier 50 | _reuseIdentifier = reuseIdentifier; 51 | 52 | // set up contentView 53 | self.contentView = [[UIView alloc] initWithFrame:self.bounds]; 54 | self.contentView.backgroundColor = [UIColor clearColor]; 55 | 56 | // set up Background 57 | self.backgroundView = [[UIView alloc] initWithFrame:self.bounds]; 58 | self.backgroundView.backgroundColor = [UIColor clearColor]; 59 | 60 | // set up selected BG 61 | self.selectedBackgroundView = [[UIView alloc] initWithFrame:self.bounds]; 62 | self.selectedBackgroundView.backgroundColor = [UIColor clearColor]; 63 | 64 | // set up highlighted BG 65 | self.highlightedBackgroundView = [[UIView alloc] initWithFrame:self.bounds]; 66 | self.highlightedBackgroundView.backgroundColor = [UIColor clearColor]; 67 | 68 | // set up titleLabel 69 | self.titleLabel = [[UILabel alloc] init]; 70 | self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 71 | self.titleLabel.backgroundColor = [UIColor clearColor]; 72 | self.titleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; 73 | self.titleLabel.textAlignment = UITextAlignmentLeft; 74 | 75 | [self.contentView addSubview: self.titleLabel]; 76 | 77 | self.clipsToBounds = YES; 78 | } 79 | return self; 80 | } 81 | 82 | 83 | 84 | //=========================================================================================== 85 | #pragma mark - Reuse 86 | - (void)prepareForReuse{} 87 | 88 | //=========================================================================================== 89 | #pragma mark - Properties 90 | - (void)setFrame:(CGRect)frame{ 91 | [super setFrame:frame]; 92 | 93 | // update title label 94 | _titleLabel.frame = CGRectMake(10.0f, 0.0f, _contentView.bounds.size.width - 10.0f, _contentView.bounds.size.height); 95 | _titleLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 96 | } 97 | 98 | - (void)setSelected:(BOOL)selected{ 99 | [self setSelected:selected animated:NO]; 100 | } 101 | 102 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated{ 103 | _selected = selected; 104 | 105 | if (animated) { 106 | [UIView animateWithDuration:0.3 animations:^{ 107 | self.selectedBackgroundView.alpha = selected?1.0f:0.0f; 108 | }]; 109 | } 110 | else{ 111 | self.selectedBackgroundView.alpha = selected?1.0f:0.0f; 112 | } 113 | } 114 | 115 | - (void)setHighlighted:(BOOL)highlighted{ 116 | [self setHighlighted:highlighted animated:NO]; 117 | } 118 | 119 | - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{ 120 | _highlighted = highlighted; 121 | 122 | if (animated) { 123 | [UIView animateWithDuration:0.3 animations:^{ 124 | self.highlightedBackgroundView.alpha = highlighted?1.0f:0.0f; 125 | }]; 126 | } 127 | else{ 128 | self.highlightedBackgroundView.alpha = highlighted?1.0f:0.0f; 129 | } 130 | } 131 | 132 | - (void)setBackgroundView:(UIView *)backgroundView{ 133 | [_backgroundView removeFromSuperview]; 134 | 135 | _backgroundView = backgroundView; 136 | 137 | _backgroundView.frame = self.bounds; 138 | _backgroundView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 139 | 140 | [self addSubview: _backgroundView]; 141 | [self sendSubviewToBack:_backgroundView]; 142 | } 143 | 144 | - (void)setContentView:(UIView *)contentView{ 145 | [_contentView removeFromSuperview]; 146 | 147 | _contentView = contentView; 148 | 149 | _contentView.frame = self.bounds; 150 | _contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 151 | _contentView.backgroundColor = [UIColor clearColor]; 152 | 153 | [self addSubview: _contentView]; 154 | [self bringSubviewToFront:_contentView]; 155 | } 156 | 157 | - (void)setSelectedBackgroundView:(UIView *)selectedBackgroundView{ 158 | [_selectedBackgroundView removeFromSuperview]; 159 | 160 | _selectedBackgroundView = selectedBackgroundView; 161 | 162 | _selectedBackgroundView.frame = self.bounds; 163 | _selectedBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 164 | 165 | _selectedBackgroundView.alpha = 0.0f; 166 | 167 | [self insertSubview:_selectedBackgroundView aboveSubview:_backgroundView]; 168 | } 169 | 170 | - (void)setHighlightedBackgroundView:(UIView *)highlightedBackgroundView{ 171 | [_highlightedBackgroundView removeFromSuperview]; 172 | 173 | _highlightedBackgroundView = highlightedBackgroundView; 174 | 175 | _highlightedBackgroundView.frame = self.bounds; 176 | _highlightedBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 177 | 178 | _highlightedBackgroundView.alpha = 0.0f; 179 | 180 | [self insertSubview:_highlightedBackgroundView aboveSubview:_selectedBackgroundView]; 181 | } 182 | 183 | @end 184 | -------------------------------------------------------------------------------- /A3GridTableViewSample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8897C0EE16240F4200DABEDF /* A3GridTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8897C0EB16240F4200DABEDF /* A3GridTableView.m */; }; 11 | 8897C0EF16240F4200DABEDF /* A3GridTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8897C0ED16240F4200DABEDF /* A3GridTableViewCell.m */; }; 12 | 88BDCC411615CD2E00BF7A03 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88BDCC401615CD2E00BF7A03 /* UIKit.framework */; }; 13 | 88BDCC431615CD2E00BF7A03 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88BDCC421615CD2E00BF7A03 /* Foundation.framework */; }; 14 | 88BDCC451615CD2E00BF7A03 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88BDCC441615CD2E00BF7A03 /* CoreGraphics.framework */; }; 15 | 88BDCC4B1615CD2E00BF7A03 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 88BDCC491615CD2E00BF7A03 /* InfoPlist.strings */; }; 16 | 88BDCC4D1615CD2E00BF7A03 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 88BDCC4C1615CD2E00BF7A03 /* main.m */; }; 17 | 88BDCC511615CD2E00BF7A03 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 88BDCC501615CD2E00BF7A03 /* AppDelegate.m */; }; 18 | 88BDCC5A1615CD2E00BF7A03 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 88BDCC591615CD2E00BF7A03 /* ViewController.m */; }; 19 | 88BDCC5D1615CD2E00BF7A03 /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88BDCC5B1615CD2E00BF7A03 /* ViewController.xib */; }; 20 | 88FFA0481860549400E12677 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 88FFA0471860549400E12677 /* Images.xcassets */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 8897C0EA16240F4200DABEDF /* A3GridTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = A3GridTableView.h; sourceTree = ""; }; 25 | 8897C0EB16240F4200DABEDF /* A3GridTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = A3GridTableView.m; sourceTree = ""; }; 26 | 8897C0EC16240F4200DABEDF /* A3GridTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = A3GridTableViewCell.h; sourceTree = ""; }; 27 | 8897C0ED16240F4200DABEDF /* A3GridTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = A3GridTableViewCell.m; sourceTree = ""; }; 28 | 88BDCC3C1615CD2E00BF7A03 /* A3GridTableViewSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = A3GridTableViewSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 88BDCC401615CD2E00BF7A03 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 30 | 88BDCC421615CD2E00BF7A03 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 31 | 88BDCC441615CD2E00BF7A03 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 32 | 88BDCC481615CD2E00BF7A03 /* A3GridTableViewSample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "A3GridTableViewSample-Info.plist"; sourceTree = ""; }; 33 | 88BDCC4A1615CD2E00BF7A03 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 34 | 88BDCC4C1615CD2E00BF7A03 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 35 | 88BDCC4E1615CD2E00BF7A03 /* A3GridTableViewSample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "A3GridTableViewSample-Prefix.pch"; sourceTree = ""; }; 36 | 88BDCC4F1615CD2E00BF7A03 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 37 | 88BDCC501615CD2E00BF7A03 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 38 | 88BDCC581615CD2E00BF7A03 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 39 | 88BDCC591615CD2E00BF7A03 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 40 | 88BDCC5C1615CD2E00BF7A03 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; 41 | 88FFA0471860549400E12677 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 88BDCC391615CD2E00BF7A03 /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | 88BDCC411615CD2E00BF7A03 /* UIKit.framework in Frameworks */, 50 | 88BDCC431615CD2E00BF7A03 /* Foundation.framework in Frameworks */, 51 | 88BDCC451615CD2E00BF7A03 /* CoreGraphics.framework in Frameworks */, 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 8897C0E916240F4200DABEDF /* A3GridTableView */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 8897C0EA16240F4200DABEDF /* A3GridTableView.h */, 62 | 8897C0EB16240F4200DABEDF /* A3GridTableView.m */, 63 | 8897C0EC16240F4200DABEDF /* A3GridTableViewCell.h */, 64 | 8897C0ED16240F4200DABEDF /* A3GridTableViewCell.m */, 65 | ); 66 | path = A3GridTableView; 67 | sourceTree = SOURCE_ROOT; 68 | }; 69 | 88BDCC311615CD2E00BF7A03 = { 70 | isa = PBXGroup; 71 | children = ( 72 | 88BDCC461615CD2E00BF7A03 /* A3GridTableViewSample */, 73 | 88BDCC3F1615CD2E00BF7A03 /* Frameworks */, 74 | 88BDCC3D1615CD2E00BF7A03 /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 88BDCC3D1615CD2E00BF7A03 /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 88BDCC3C1615CD2E00BF7A03 /* A3GridTableViewSample.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 88BDCC3F1615CD2E00BF7A03 /* Frameworks */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 88BDCC401615CD2E00BF7A03 /* UIKit.framework */, 90 | 88BDCC421615CD2E00BF7A03 /* Foundation.framework */, 91 | 88BDCC441615CD2E00BF7A03 /* CoreGraphics.framework */, 92 | ); 93 | name = Frameworks; 94 | sourceTree = ""; 95 | }; 96 | 88BDCC461615CD2E00BF7A03 /* A3GridTableViewSample */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 88BDCC4F1615CD2E00BF7A03 /* AppDelegate.h */, 100 | 88BDCC501615CD2E00BF7A03 /* AppDelegate.m */, 101 | 88BDCC581615CD2E00BF7A03 /* ViewController.h */, 102 | 88BDCC591615CD2E00BF7A03 /* ViewController.m */, 103 | 88BDCC5B1615CD2E00BF7A03 /* ViewController.xib */, 104 | 8897C0E916240F4200DABEDF /* A3GridTableView */, 105 | 88FFA0471860549400E12677 /* Images.xcassets */, 106 | 88BDCC471615CD2E00BF7A03 /* Supporting Files */, 107 | ); 108 | path = A3GridTableViewSample; 109 | sourceTree = ""; 110 | }; 111 | 88BDCC471615CD2E00BF7A03 /* Supporting Files */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 88BDCC481615CD2E00BF7A03 /* A3GridTableViewSample-Info.plist */, 115 | 88BDCC491615CD2E00BF7A03 /* InfoPlist.strings */, 116 | 88BDCC4C1615CD2E00BF7A03 /* main.m */, 117 | 88BDCC4E1615CD2E00BF7A03 /* A3GridTableViewSample-Prefix.pch */, 118 | ); 119 | name = "Supporting Files"; 120 | sourceTree = ""; 121 | }; 122 | /* End PBXGroup section */ 123 | 124 | /* Begin PBXNativeTarget section */ 125 | 88BDCC3B1615CD2E00BF7A03 /* A3GridTableViewSample */ = { 126 | isa = PBXNativeTarget; 127 | buildConfigurationList = 88BDCC601615CD2E00BF7A03 /* Build configuration list for PBXNativeTarget "A3GridTableViewSample" */; 128 | buildPhases = ( 129 | 88BDCC381615CD2E00BF7A03 /* Sources */, 130 | 88BDCC391615CD2E00BF7A03 /* Frameworks */, 131 | 88BDCC3A1615CD2E00BF7A03 /* Resources */, 132 | ); 133 | buildRules = ( 134 | ); 135 | dependencies = ( 136 | ); 137 | name = A3GridTableViewSample; 138 | productName = A3GridTableViewSample; 139 | productReference = 88BDCC3C1615CD2E00BF7A03 /* A3GridTableViewSample.app */; 140 | productType = "com.apple.product-type.application"; 141 | }; 142 | /* End PBXNativeTarget section */ 143 | 144 | /* Begin PBXProject section */ 145 | 88BDCC331615CD2E00BF7A03 /* Project object */ = { 146 | isa = PBXProject; 147 | attributes = { 148 | LastUpgradeCheck = 0450; 149 | ORGANIZATIONNAME = AllAboutApps; 150 | }; 151 | buildConfigurationList = 88BDCC361615CD2E00BF7A03 /* Build configuration list for PBXProject "A3GridTableViewSample" */; 152 | compatibilityVersion = "Xcode 3.2"; 153 | developmentRegion = English; 154 | hasScannedForEncodings = 0; 155 | knownRegions = ( 156 | en, 157 | ); 158 | mainGroup = 88BDCC311615CD2E00BF7A03; 159 | productRefGroup = 88BDCC3D1615CD2E00BF7A03 /* Products */; 160 | projectDirPath = ""; 161 | projectRoot = ""; 162 | targets = ( 163 | 88BDCC3B1615CD2E00BF7A03 /* A3GridTableViewSample */, 164 | ); 165 | }; 166 | /* End PBXProject section */ 167 | 168 | /* Begin PBXResourcesBuildPhase section */ 169 | 88BDCC3A1615CD2E00BF7A03 /* Resources */ = { 170 | isa = PBXResourcesBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | 88BDCC4B1615CD2E00BF7A03 /* InfoPlist.strings in Resources */, 174 | 88FFA0481860549400E12677 /* Images.xcassets in Resources */, 175 | 88BDCC5D1615CD2E00BF7A03 /* ViewController.xib in Resources */, 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXResourcesBuildPhase section */ 180 | 181 | /* Begin PBXSourcesBuildPhase section */ 182 | 88BDCC381615CD2E00BF7A03 /* Sources */ = { 183 | isa = PBXSourcesBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | 88BDCC4D1615CD2E00BF7A03 /* main.m in Sources */, 187 | 88BDCC511615CD2E00BF7A03 /* AppDelegate.m in Sources */, 188 | 88BDCC5A1615CD2E00BF7A03 /* ViewController.m in Sources */, 189 | 8897C0EE16240F4200DABEDF /* A3GridTableView.m in Sources */, 190 | 8897C0EF16240F4200DABEDF /* A3GridTableViewCell.m in Sources */, 191 | ); 192 | runOnlyForDeploymentPostprocessing = 0; 193 | }; 194 | /* End PBXSourcesBuildPhase section */ 195 | 196 | /* Begin PBXVariantGroup section */ 197 | 88BDCC491615CD2E00BF7A03 /* InfoPlist.strings */ = { 198 | isa = PBXVariantGroup; 199 | children = ( 200 | 88BDCC4A1615CD2E00BF7A03 /* en */, 201 | ); 202 | name = InfoPlist.strings; 203 | sourceTree = ""; 204 | }; 205 | 88BDCC5B1615CD2E00BF7A03 /* ViewController.xib */ = { 206 | isa = PBXVariantGroup; 207 | children = ( 208 | 88BDCC5C1615CD2E00BF7A03 /* en */, 209 | ); 210 | name = ViewController.xib; 211 | sourceTree = ""; 212 | }; 213 | /* End PBXVariantGroup section */ 214 | 215 | /* Begin XCBuildConfiguration section */ 216 | 88BDCC5E1615CD2E00BF7A03 /* Debug */ = { 217 | isa = XCBuildConfiguration; 218 | buildSettings = { 219 | ALWAYS_SEARCH_USER_PATHS = NO; 220 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 221 | CLANG_CXX_LIBRARY = "libc++"; 222 | CLANG_WARN_EMPTY_BODY = YES; 223 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 224 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 225 | COPY_PHASE_STRIP = NO; 226 | GCC_C_LANGUAGE_STANDARD = gnu99; 227 | GCC_DYNAMIC_NO_PIC = NO; 228 | GCC_OPTIMIZATION_LEVEL = 0; 229 | GCC_PREPROCESSOR_DEFINITIONS = ( 230 | "DEBUG=1", 231 | "$(inherited)", 232 | ); 233 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 234 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 235 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 238 | SDKROOT = iphoneos; 239 | }; 240 | name = Debug; 241 | }; 242 | 88BDCC5F1615CD2E00BF7A03 /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | ALWAYS_SEARCH_USER_PATHS = NO; 246 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 247 | CLANG_CXX_LIBRARY = "libc++"; 248 | CLANG_WARN_EMPTY_BODY = YES; 249 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 250 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 251 | COPY_PHASE_STRIP = YES; 252 | GCC_C_LANGUAGE_STANDARD = gnu99; 253 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 254 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 257 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 258 | SDKROOT = iphoneos; 259 | VALIDATE_PRODUCT = YES; 260 | }; 261 | name = Release; 262 | }; 263 | 88BDCC611615CD2E00BF7A03 /* Debug */ = { 264 | isa = XCBuildConfiguration; 265 | buildSettings = { 266 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 267 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CODE_SIGN_IDENTITY = "iPhone Developer"; 270 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 271 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 272 | GCC_PREFIX_HEADER = "A3GridTableViewSample/A3GridTableViewSample-Prefix.pch"; 273 | INFOPLIST_FILE = "A3GridTableViewSample/A3GridTableViewSample-Info.plist"; 274 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 275 | PRODUCT_NAME = "$(TARGET_NAME)"; 276 | PROVISIONING_PROFILE = ""; 277 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 278 | TARGETED_DEVICE_FAMILY = "1,2"; 279 | WRAPPER_EXTENSION = app; 280 | }; 281 | name = Debug; 282 | }; 283 | 88BDCC621615CD2E00BF7A03 /* Release */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 287 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 288 | CLANG_ENABLE_OBJC_ARC = YES; 289 | CODE_SIGN_IDENTITY = "iPhone Developer"; 290 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 291 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 292 | GCC_PREFIX_HEADER = "A3GridTableViewSample/A3GridTableViewSample-Prefix.pch"; 293 | INFOPLIST_FILE = "A3GridTableViewSample/A3GridTableViewSample-Info.plist"; 294 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 295 | PRODUCT_NAME = "$(TARGET_NAME)"; 296 | PROVISIONING_PROFILE = ""; 297 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 298 | TARGETED_DEVICE_FAMILY = "1,2"; 299 | WRAPPER_EXTENSION = app; 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | 88BDCC361615CD2E00BF7A03 /* Build configuration list for PBXProject "A3GridTableViewSample" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | 88BDCC5E1615CD2E00BF7A03 /* Debug */, 310 | 88BDCC5F1615CD2E00BF7A03 /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | 88BDCC601615CD2E00BF7A03 /* Build configuration list for PBXNativeTarget "A3GridTableViewSample" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | 88BDCC611615CD2E00BF7A03 /* Debug */, 319 | 88BDCC621615CD2E00BF7A03 /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = 88BDCC331615CD2E00BF7A03 /* Project object */; 327 | } 328 | -------------------------------------------------------------------------------- /A3GridTableViewSample/A3GridTableViewSample-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundleIcons~ipad 14 | 15 | CFBundleIdentifier 16 | at.allaboutapps.${PRODUCT_NAME:rfc1034identifier} 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | ${PRODUCT_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 1.0 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | 1.0 29 | LSRequiresIPhoneOS 30 | 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /A3GridTableViewSample/A3GridTableViewSample-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'A3GridTableViewSample' target in the 'A3GridTableViewSample' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /A3GridTableViewSample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // A3GridTableViewSample 4 | // 5 | // Created by Botond Kis on 28.09.12. 6 | // Copyright (c) 2012 AllAboutApps. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /A3GridTableViewSample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // A3GridTableViewSample 4 | // 5 | // Created by Botond Kis on 28.09.12. 6 | // Copyright (c) 2012 AllAboutApps. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | 13 | @implementation AppDelegate 14 | 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 19 | // Override point for customization after application launch. 20 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 21 | self.window.rootViewController = self.viewController; 22 | [self.window makeKeyAndVisible]; 23 | return YES; 24 | } 25 | 26 | - (void)applicationWillResignActive:(UIApplication *)application 27 | { 28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 29 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 30 | } 31 | 32 | - (void)applicationDidEnterBackground:(UIApplication *)application 33 | { 34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | - (void)applicationWillEnterForeground:(UIApplication *)application 39 | { 40 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 41 | } 42 | 43 | - (void)applicationDidBecomeActive:(UIApplication *)application 44 | { 45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 46 | } 47 | 48 | - (void)applicationWillTerminate:(UIApplication *)application 49 | { 50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "1x", 6 | "size" : "57x57" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "2x", 11 | "size" : "57x57" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "60x60" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "scale" : "1x", 21 | "size" : "72x72" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "scale" : "2x", 26 | "size" : "72x72" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "scale" : "1x", 31 | "size" : "76x76" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "scale" : "2x", 36 | "size" : "76x76" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "1x", 41 | "size" : "29x29" 42 | }, 43 | { 44 | "idiom" : "iphone", 45 | "scale" : "2x", 46 | "size" : "29x29" 47 | }, 48 | { 49 | "idiom" : "iphone", 50 | "scale" : "2x", 51 | "size" : "40x40" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "50x50" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "50x50" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "29x29" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "29x29" 82 | } 83 | ], 84 | "info" : { 85 | "version" : 1, 86 | "author" : "xcode" 87 | } 88 | } -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "filename" : "Default.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "orientation" : "portrait", 11 | "idiom" : "iphone", 12 | "filename" : "Default@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "orientation" : "portrait", 17 | "idiom" : "iphone", 18 | "filename" : "Default-568h@2x.png", 19 | "subtype" : "retina4", 20 | "scale" : "2x" 21 | }, 22 | { 23 | "orientation" : "portrait", 24 | "idiom" : "iphone", 25 | "filename" : "Default@2x.png", 26 | "minimum-system-version" : "7.0", 27 | "scale" : "2x" 28 | }, 29 | { 30 | "orientation" : "portrait", 31 | "idiom" : "iphone", 32 | "filename" : "Default-568h@2x.png", 33 | "minimum-system-version" : "7.0", 34 | "subtype" : "retina4", 35 | "scale" : "2x" 36 | }, 37 | { 38 | "orientation" : "portrait", 39 | "idiom" : "ipad", 40 | "extent" : "to-status-bar", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "orientation" : "portrait", 45 | "idiom" : "ipad", 46 | "extent" : "to-status-bar", 47 | "scale" : "2x" 48 | }, 49 | { 50 | "orientation" : "landscape", 51 | "idiom" : "ipad", 52 | "extent" : "to-status-bar", 53 | "scale" : "1x" 54 | }, 55 | { 56 | "orientation" : "landscape", 57 | "idiom" : "ipad", 58 | "extent" : "to-status-bar", 59 | "scale" : "2x" 60 | }, 61 | { 62 | "orientation" : "portrait", 63 | "idiom" : "ipad", 64 | "minimum-system-version" : "7.0", 65 | "extent" : "full-screen", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "orientation" : "portrait", 70 | "idiom" : "ipad", 71 | "minimum-system-version" : "7.0", 72 | "extent" : "full-screen", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "orientation" : "landscape", 77 | "idiom" : "ipad", 78 | "minimum-system-version" : "7.0", 79 | "extent" : "full-screen", 80 | "scale" : "1x" 81 | }, 82 | { 83 | "orientation" : "landscape", 84 | "idiom" : "ipad", 85 | "minimum-system-version" : "7.0", 86 | "extent" : "full-screen", 87 | "scale" : "2x" 88 | } 89 | ], 90 | "info" : { 91 | "version" : 1, 92 | "author" : "xcode" 93 | } 94 | } -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allaboutapps/A3GridTableView/278a0b5561ad04df507fb825ad3b3788d688e3f7/A3GridTableViewSample/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/LaunchImage.launchimage/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allaboutapps/A3GridTableView/278a0b5561ad04df507fb825ad3b3788d688e3f7/A3GridTableViewSample/Images.xcassets/LaunchImage.launchimage/Default.png -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/LaunchImage.launchimage/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allaboutapps/A3GridTableView/278a0b5561ad04df507fb825ad3b3788d688e3f7/A3GridTableViewSample/Images.xcassets/LaunchImage.launchimage/Default@2x.png -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/cellBG-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "cellBG-highlighted.png" 7 | } 8 | ], 9 | "info" : { 10 | "version" : 1, 11 | "author" : "xcode" 12 | } 13 | } -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/cellBG-highlighted.imageset/cellBG-highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allaboutapps/A3GridTableView/278a0b5561ad04df507fb825ad3b3788d688e3f7/A3GridTableViewSample/Images.xcassets/cellBG-highlighted.imageset/cellBG-highlighted.png -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/cellBG-normal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "cellBG-normal.png" 7 | } 8 | ], 9 | "info" : { 10 | "version" : 1, 11 | "author" : "xcode" 12 | } 13 | } -------------------------------------------------------------------------------- /A3GridTableViewSample/Images.xcassets/cellBG-normal.imageset/cellBG-normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allaboutapps/A3GridTableView/278a0b5561ad04df507fb825ad3b3788d688e3f7/A3GridTableViewSample/Images.xcassets/cellBG-normal.imageset/cellBG-normal.png -------------------------------------------------------------------------------- /A3GridTableViewSample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // A3GridTableViewSample 4 | // 5 | // Created by Botond Kis on 28.09.12. 6 | // Copyright (c) 2012 AllAboutApps. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "A3GridTableView.h" 11 | 12 | @interface ViewController : UIViewController { 13 | // the Gride Table View 14 | A3GridTableView *gridTableView; 15 | } 16 | 17 | // reaload button 18 | @property (strong, nonatomic) IBOutlet UIButton *buttonReload; 19 | - (IBAction)buttonReloadTouchUpInside:(id)sender; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /A3GridTableViewSample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // A3GridTableViewSample 4 | // 5 | // Created by Botond Kis on 28.09.12. 6 | // Copyright (c) 2012 AllAboutApps. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController (){ 12 | NSMutableArray *numberOfRowsInSection; 13 | CGFloat dayheight; 14 | } 15 | @property (nonatomic, strong) UIImage *normalImage; 16 | @property (nonatomic, strong) UIImage *selectedImage; 17 | 18 | @end 19 | 20 | #define ITEMS 500 21 | 22 | @implementation ViewController 23 | 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | // Do any additional setup after loading the view, typically from a nib. 28 | 29 | // initialize Random Data 30 | numberOfRowsInSection = [[NSMutableArray alloc] init]; 31 | for (int i = 0; i < ITEMS; i++) { 32 | [numberOfRowsInSection addObject:[NSNumber numberWithInt: arc4random()%60+1]]; 33 | } 34 | 35 | dayheight = 1000.0f; 36 | 37 | // Initialize Grid View 38 | gridTableView = [[A3GridTableView alloc] initWithFrame:self.view.bounds]; 39 | gridTableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 40 | 41 | // images 42 | self.normalImage = [UIImage imageNamed:@"cellBG-normal"]; 43 | self.normalImage = [self.normalImage resizableImageWithCapInsets:UIEdgeInsetsMake(14, 16, 18, 16)]; 44 | self.selectedImage = [UIImage imageNamed:@"cellBG-highlighted"]; 45 | self.selectedImage = [self.selectedImage resizableImageWithCapInsets:UIEdgeInsetsMake(14, 16, 18, 16)]; 46 | 47 | // set datasource and delegate 48 | gridTableView.dataSource = self; 49 | gridTableView.delegate = self; 50 | 51 | // set paging 52 | gridTableView.pagingPosition = A3GridTableViewCellAlignmentCenter; 53 | gridTableView.gridTableViewPagingEnabled = YES; 54 | gridTableView.backgroundColor = [UIColor lightGrayColor]; 55 | 56 | // scrolling 57 | gridTableView.directionalLockEnabled = YES; 58 | 59 | // add as subview 60 | [self.view addSubview:gridTableView]; 61 | [self.view sendSubviewToBack:gridTableView]; 62 | } 63 | 64 | - (void)didReceiveMemoryWarning 65 | { 66 | [super didReceiveMemoryWarning]; 67 | // Dispose of any resources that can be recreated. 68 | } 69 | 70 | 71 | - (void)viewDidUnload { 72 | [self setButtonReload:nil]; 73 | [super viewDidUnload]; 74 | } 75 | 76 | - (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ 77 | return YES; 78 | } 79 | 80 | //=========================================================================================== 81 | #pragma mark - DataSource 82 | 83 | // Data handling 84 | - (NSInteger)numberOfSectionsInA3GridTableView:(A3GridTableView *)aGridTableView{ 85 | return ITEMS; 86 | } 87 | 88 | - (NSInteger)A3GridTableView:(A3GridTableView *) aGridTableView numberOfRowsInSection:(NSInteger) section{ 89 | NSNumber *n = numberOfRowsInSection[section]; 90 | return [n integerValue]; 91 | } 92 | 93 | // header handling 94 | - (A3GridTableViewCell *)A3GridTableView:(A3GridTableView *)aGridTableView headerForSection:(NSInteger)section{ 95 | A3GridTableViewCell *headerCell; 96 | 97 | headerCell = [aGridTableView dequeueReusableHeaderWithIdentifier:@"headerID"]; 98 | 99 | if (!headerCell) { 100 | headerCell = [[A3GridTableViewCell alloc] initWithReuseIdentifier:@"headerID"]; 101 | UIImageView *normalBG = [[UIImageView alloc] initWithImage:self.normalImage]; 102 | UIImageView *selectedBG = [[UIImageView alloc] initWithImage:self.selectedImage]; 103 | headerCell.backgroundView = normalBG; 104 | headerCell.highlightedBackgroundView = selectedBG; 105 | 106 | headerCell.titleLabel.textAlignment = UITextAlignmentCenter; 107 | headerCell.backgroundView.backgroundColor = [UIColor clearColor]; 108 | } 109 | 110 | headerCell.titleLabel.text = [NSString stringWithFormat:@"Header: %d", section]; 111 | 112 | return headerCell; 113 | } 114 | 115 | - (CGFloat)heightForHeadersInA3GridTableView:(A3GridTableView *)aGridTableView{ 116 | return 88.0f; 117 | } 118 | 119 | - (CGFloat)A3GridTableView:(A3GridTableView *)aGridTableView widthForSection:(NSInteger)section{ 120 | return 300; 121 | } 122 | 123 | 124 | 125 | // Cell handling 126 | - (A3GridTableViewCell *)A3GridTableView:(A3GridTableView *)aGridTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 127 | A3GridTableViewCell *cell; 128 | cell = [aGridTableView dequeueReusableCellWithIdentifier:@"cellID"]; 129 | 130 | if (!cell) { 131 | cell = [[A3GridTableViewCell alloc] initWithReuseIdentifier:@"cellID"]; 132 | cell.backgroundColor = [UIColor clearColor]; 133 | UIImageView *normalBG = [[UIImageView alloc] initWithImage:self.normalImage]; 134 | UIImageView *selectedBG = [[UIImageView alloc] initWithImage:self.selectedImage]; 135 | cell.backgroundView = normalBG; 136 | cell.highlightedBackgroundView = selectedBG; 137 | } 138 | cell.titleLabel.text = [NSString stringWithFormat:@"Cell: %d-%d", indexPath.section, indexPath.row]; 139 | 140 | return cell; 141 | } 142 | 143 | - (CGFloat)A3GridTableView:(A3GridTableView *)aGridTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 144 | NSNumber *n = numberOfRowsInSection[indexPath.section]; 145 | return (int)(dayheight/n.integerValue); 146 | } 147 | 148 | 149 | //=========================================================================================== 150 | #pragma mark - Button Actions 151 | 152 | - (IBAction)buttonReloadTouchUpInside:(id)sender { 153 | // Randomize height and reload Table 154 | dayheight = (arc4random()%10+2)*1000; 155 | [gridTableView reloadCellsWithViewAnimation:YES]; 156 | } 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /A3GridTableViewSample/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /A3GridTableViewSample/en.lproj/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1536 5 | 12C54 6 | 2840 7 | 1187.34 8 | 625.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1926 12 | 13 | 14 | IBProxyObject 15 | IBUIButton 16 | IBUIView 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 265 41 | {{178, 485}, {122, 44}} 42 | 43 | 44 | 45 | _NS:9 46 | NO 47 | IBCocoaTouchFramework 48 | 0 49 | 0 50 | 1 51 | reload 52 | 53 | 3 54 | MQA 55 | 56 | 57 | 1 58 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 59 | 60 | 61 | 3 62 | MC41AA 63 | 64 | 65 | 2 66 | 15 67 | 68 | 69 | Helvetica-Bold 70 | 15 71 | 16 72 | 73 | 74 | 75 | {{0, 20}, {320, 548}} 76 | 77 | 78 | 79 | 80 | 3 81 | MC43NQA 82 | 83 | 2 84 | 85 | 86 | NO 87 | 88 | 89 | IBUIScreenMetrics 90 | 91 | YES 92 | 93 | 94 | 95 | 96 | 97 | {320, 568} 98 | {568, 320} 99 | 100 | 101 | IBCocoaTouchFramework 102 | Retina 4 Full Screen 103 | 2 104 | 105 | IBCocoaTouchFramework 106 | 107 | 108 | 109 | 110 | 111 | 112 | view 113 | 114 | 115 | 116 | 7 117 | 118 | 119 | 120 | buttonReload 121 | 122 | 123 | 124 | 16 125 | 126 | 127 | 128 | buttonReloadTouchUpInside: 129 | 130 | 131 | 7 132 | 133 | 17 134 | 135 | 136 | 137 | 138 | 139 | 0 140 | 141 | 142 | 143 | 144 | 145 | -1 146 | 147 | 148 | File's Owner 149 | 150 | 151 | -2 152 | 153 | 154 | 155 | 156 | 6 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 12 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | ViewController 173 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 174 | UIResponder 175 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 176 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 177 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 178 | 179 | 180 | 181 | 182 | 183 | 17 184 | 185 | 186 | 187 | 188 | ViewController 189 | UIViewController 190 | 191 | buttonReloadTouchUpInside: 192 | id 193 | 194 | 195 | buttonReloadTouchUpInside: 196 | 197 | buttonReloadTouchUpInside: 198 | id 199 | 200 | 201 | 202 | buttonReload 203 | UIButton 204 | 205 | 206 | buttonReload 207 | 208 | buttonReload 209 | UIButton 210 | 211 | 212 | 213 | IBProjectSource 214 | ./Classes/ViewController.h 215 | 216 | 217 | 218 | 219 | 0 220 | IBCocoaTouchFramework 221 | YES 222 | 3 223 | 1926 224 | 225 | 226 | -------------------------------------------------------------------------------- /A3GridTableViewSample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // A3GridTableViewSample 4 | // 5 | // Created by Botond Kis on 28.09.12. 6 | // Copyright (c) 2012 AllAboutApps. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /A3GridTableViewSampleIPad.m4v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allaboutapps/A3GridTableView/278a0b5561ad04df507fb825ad3b3788d688e3f7/A3GridTableViewSampleIPad.m4v -------------------------------------------------------------------------------- /A3GridTableViewSampleIPhone.m4v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allaboutapps/A3GridTableView/278a0b5561ad04df507fb825ad3b3788d688e3f7/A3GridTableViewSampleIPhone.m4v -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | ..???????????????????????????????????????????????????. 3 | .,?????============================================?????. . 4 | +???=================================================+???. 5 | ???===================================================+???. 6 | ??+====================================================??? 7 | ??==========================~~~=========================?? 8 | ??==================...................:================?? 9 | ??===============.........................==============?? 10 | ??=============.............................============?? 11 | ??===========~...............................===========?? 12 | ??===========............,======~............,==========?? 13 | ??==========...........============...........==========?? 14 | ??==========..........=============~..........==========?? 15 | ??=========~..........==============..........==========?? 16 | ??=================================,..........==========?? 17 | ?????+===========================:............======+????? 18 | ???????????=============~:....................+??????????? 19 | ?????????????????:............................???????????? 20 | ??????????????=...............................???????????? 21 | ????????????=....................~II..........???????????? 22 | ???????????+.............=I????????I..........???????????? 23 | ???????????...........+????????????I..........???????????? 24 | ??????????~..........???????????????..........???????????? 25 | ??????????...........??????????????,..........???????????? 26 | ??????????...........??????????????...........I??????????? 27 | ??????????...........I???????????+............I??????????? 28 | ???????????............I??????I~..............I??????????? 29 | ???????????,..................................???????????? 30 | IIIIIIIIIIII..................................=IIIIIIIIII? 31 | IIIIIIIIIIIII~....................=?...........IIIIIIIIII? 32 | IIIIIIIIIIIIIII+...............:IIII+..........?IIIIIIIIII 33 | IIIIIIIIIIIIIIIIIIII?=~~=+?IIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 34 | IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 35 | IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 36 | .IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII.. 37 | IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII . 38 | .~IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII. 39 | ....................IIIIIIIIIII:............... . 40 | . ..IIIIIIIII,. 41 | .IIIIIII+ . 42 | .IIIIII. 43 | ..III?. 44 | II. 45 | .. . 46 | *********************************************************** 47 | 48 | A3GridView for iOS 49 | Copyright (c) 2012, aaa - All About Apps 50 | Developed by Botond Kis 51 | All rights reserved. 52 | 53 | Redistribution and use in source and binary forms, with or without modification, 54 | are permitted provided that the following conditions are met: 55 | 56 | - Redistributions of source code must retain the above copyright notice, this list 57 | of conditions and the following disclaimer. 58 | 59 | - Redistributions in binary form must reproduce the above copyright notice, this list 60 | of conditions and the following disclaimer in the documentation and/or other materials 61 | provided with the distribution. 62 | 63 | - Neither the name of the "aaa - All About Apps" nor the names of its contributors may be used 64 | to endorse or promote products derived from this software without specific prior written 65 | permission. 66 | 67 | 68 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 69 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 70 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 71 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 72 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 73 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 74 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 75 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 76 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 77 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | #What is A3GridTableView? 3 | **A3GridTableView** is a `UIScrollView` subclass with a high performance GridView style layouting. 4 | It has similar delegate methods to a `UITableView` and can be even used like one. 5 | The difference is that the **A3GridTableView** aligns his section in collumns and not in one flow. 6 | 7 | It is written in *Objective-C* and works for all iOS applications and uses ARC. 8 | 9 | ##Video: 10 | ![A3GridTableView iPhone sample](https://dl.dropbox.com/u/9934540/aaa/A3GridTableViewSampleIPhone.gif "A3GridTableView iPhone Sample Video") 11 | ![A3GridTableView iPad sample](https://dl.dropbox.com/u/9934540/aaa/A3GridTableViewSampleIPad.gif "A3GridTableView iPad Sample Video") 12 | 13 | 14 | ##Usage: 15 | 16 | Initialize a **A3GridTableView** like any other View by code or in the InterfaceBuilder. 17 | Set your ViewController as dataSource and delegate of the **A3GridTableView** and implement the required dataSource methods: 18 | 19 | - (NSInteger)numberOfSectionsInA3GridTableView:(A3GridTableView *) gridTableView; 20 | - (NSInteger)A3GridTableView:(A3GridTableView *) tableView numberOfRowsInSection:(NSInteger) section; 21 | - (A3GridTableViewCell *)A3GridTableView:(A3GridTableView *)gridTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; 22 | 23 | You can find all optional dataSource and delegate methods like `heightForRowAtIndexPath:` well documented with explanations in the [A3GridTableView.h header](https://github.com/allaboutapps/A3GridTableView/blob/master/A3GridTableView/A3GridTableView.h) file. 24 | 25 | The dataSource method `cellForRowAtIndexPath:` requires a **A3GridTableViewCell** (or a subclass) which properties can also be seen in [A3GridTableViewCell.h header](https://github.com/allaboutapps/A3GridTableView/blob/master/A3GridTableView/A3GridTableViewCell.h) file. 26 | 27 | #License: 28 | [See our BSD 3-Clause License](https://github.com/allaboutapps/A3GridTableView/blob/master/LICENSE.txt) 29 | 30 | #Contribute: 31 | Feel free to fork and make pull requests! We are also very happy if you tell us about your app(s) which use this control. 32 | 33 | 34 | ![aaa - AllAboutApps](https://dl.dropbox.com/u/9934540/aaa/aaaLogo.png "aaa - AllAboutApps") 35 | [© allaboutapps 2013](http://www.allaboutapps.at) --------------------------------------------------------------------------------