├── .gitignore ├── LICENSE ├── NGVaryingGridView ├── NGVaryingGridView.xcodeproj │ └── project.pbxproj └── NGVaryingGridView │ ├── NGVaryingGridView-Prefix.pch │ ├── NGVaryingGridView.h │ └── NGVaryingGridView.m ├── NGVaryingGridViewDemo ├── NGVaryingGridViewDemo.xcodeproj │ └── project.pbxproj └── NGVaryingGridViewDemo │ ├── NGAppDelegate.h │ ├── NGAppDelegate.m │ ├── NGTimeTableCell.h │ ├── NGTimeTableCell.m │ ├── NGVaryingGridViewDemo-Info.plist │ ├── NGVaryingGridViewDemo-Prefix.pch │ ├── NGViewController.h │ ├── NGViewController.m │ ├── en.lproj │ └── InfoPlist.strings │ └── main.m └── 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 NOUSguide Inc. (http://www.nousguide.com/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | Please contact info@nousguide.com to purchase a license without copyright notice. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /NGVaryingGridView/NGVaryingGridView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6A5A96AB153FFDF2004EA62B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A5A96AA153FFDF2004EA62B /* Foundation.framework */; }; 11 | 6A5A96B1153FFDF2004EA62B /* NGVaryingGridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A5A96B0153FFDF2004EA62B /* NGVaryingGridView.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 6A5A96A7153FFDF2004EA62B /* libNGVaryingGridView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libNGVaryingGridView.a; sourceTree = BUILT_PRODUCTS_DIR; }; 16 | 6A5A96AA153FFDF2004EA62B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 17 | 6A5A96AE153FFDF2004EA62B /* NGVaryingGridView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NGVaryingGridView-Prefix.pch"; sourceTree = ""; }; 18 | 6A5A96AF153FFDF2004EA62B /* NGVaryingGridView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NGVaryingGridView.h; sourceTree = ""; }; 19 | 6A5A96B0153FFDF2004EA62B /* NGVaryingGridView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NGVaryingGridView.m; sourceTree = ""; }; 20 | /* End PBXFileReference section */ 21 | 22 | /* Begin PBXFrameworksBuildPhase section */ 23 | 6A5A96A4153FFDF2004EA62B /* Frameworks */ = { 24 | isa = PBXFrameworksBuildPhase; 25 | buildActionMask = 2147483647; 26 | files = ( 27 | 6A5A96AB153FFDF2004EA62B /* Foundation.framework in Frameworks */, 28 | ); 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXFrameworksBuildPhase section */ 32 | 33 | /* Begin PBXGroup section */ 34 | 6A5A969C153FFDF2004EA62B = { 35 | isa = PBXGroup; 36 | children = ( 37 | 6A5A96AC153FFDF2004EA62B /* NGVaryingGridView */, 38 | 6A5A96A9153FFDF2004EA62B /* Frameworks */, 39 | 6A5A96A8153FFDF2004EA62B /* Products */, 40 | ); 41 | sourceTree = ""; 42 | }; 43 | 6A5A96A8153FFDF2004EA62B /* Products */ = { 44 | isa = PBXGroup; 45 | children = ( 46 | 6A5A96A7153FFDF2004EA62B /* libNGVaryingGridView.a */, 47 | ); 48 | name = Products; 49 | sourceTree = ""; 50 | }; 51 | 6A5A96A9153FFDF2004EA62B /* Frameworks */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | 6A5A96AA153FFDF2004EA62B /* Foundation.framework */, 55 | ); 56 | name = Frameworks; 57 | sourceTree = ""; 58 | }; 59 | 6A5A96AC153FFDF2004EA62B /* NGVaryingGridView */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | 6A5A96AF153FFDF2004EA62B /* NGVaryingGridView.h */, 63 | 6A5A96B0153FFDF2004EA62B /* NGVaryingGridView.m */, 64 | 6A5A96AD153FFDF2004EA62B /* Supporting Files */, 65 | ); 66 | path = NGVaryingGridView; 67 | sourceTree = ""; 68 | }; 69 | 6A5A96AD153FFDF2004EA62B /* Supporting Files */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 6A5A96AE153FFDF2004EA62B /* NGVaryingGridView-Prefix.pch */, 73 | ); 74 | name = "Supporting Files"; 75 | sourceTree = ""; 76 | }; 77 | /* End PBXGroup section */ 78 | 79 | /* Begin PBXHeadersBuildPhase section */ 80 | 6A5A96A5153FFDF2004EA62B /* Headers */ = { 81 | isa = PBXHeadersBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXHeadersBuildPhase section */ 88 | 89 | /* Begin PBXNativeTarget section */ 90 | 6A5A96A6153FFDF2004EA62B /* NGVaryingGridView */ = { 91 | isa = PBXNativeTarget; 92 | buildConfigurationList = 6A5A96B4153FFDF2004EA62B /* Build configuration list for PBXNativeTarget "NGVaryingGridView" */; 93 | buildPhases = ( 94 | 6A5A96A3153FFDF2004EA62B /* Sources */, 95 | 6A5A96A4153FFDF2004EA62B /* Frameworks */, 96 | 6A5A96A5153FFDF2004EA62B /* Headers */, 97 | ); 98 | buildRules = ( 99 | ); 100 | dependencies = ( 101 | ); 102 | name = NGVaryingGridView; 103 | productName = NGVaryingGridView; 104 | productReference = 6A5A96A7153FFDF2004EA62B /* libNGVaryingGridView.a */; 105 | productType = "com.apple.product-type.library.static"; 106 | }; 107 | /* End PBXNativeTarget section */ 108 | 109 | /* Begin PBXProject section */ 110 | 6A5A969E153FFDF2004EA62B /* Project object */ = { 111 | isa = PBXProject; 112 | attributes = { 113 | LastUpgradeCheck = 0610; 114 | ORGANIZATIONNAME = "NOUS Wissensmanagement GmbH"; 115 | }; 116 | buildConfigurationList = 6A5A96A1153FFDF2004EA62B /* Build configuration list for PBXProject "NGVaryingGridView" */; 117 | compatibilityVersion = "Xcode 3.2"; 118 | developmentRegion = English; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | ); 123 | mainGroup = 6A5A969C153FFDF2004EA62B; 124 | productRefGroup = 6A5A96A8153FFDF2004EA62B /* Products */; 125 | projectDirPath = ""; 126 | projectRoot = ""; 127 | targets = ( 128 | 6A5A96A6153FFDF2004EA62B /* NGVaryingGridView */, 129 | ); 130 | }; 131 | /* End PBXProject section */ 132 | 133 | /* Begin PBXSourcesBuildPhase section */ 134 | 6A5A96A3153FFDF2004EA62B /* Sources */ = { 135 | isa = PBXSourcesBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | 6A5A96B1153FFDF2004EA62B /* NGVaryingGridView.m in Sources */, 139 | ); 140 | runOnlyForDeploymentPostprocessing = 0; 141 | }; 142 | /* End PBXSourcesBuildPhase section */ 143 | 144 | /* Begin XCBuildConfiguration section */ 145 | 6A5A96B2153FFDF2004EA62B /* Debug */ = { 146 | isa = XCBuildConfiguration; 147 | buildSettings = { 148 | ALWAYS_SEARCH_USER_PATHS = NO; 149 | CLANG_ENABLE_OBJC_ARC = YES; 150 | CLANG_WARN_BOOL_CONVERSION = YES; 151 | CLANG_WARN_CONSTANT_CONVERSION = YES; 152 | CLANG_WARN_EMPTY_BODY = YES; 153 | CLANG_WARN_ENUM_CONVERSION = YES; 154 | CLANG_WARN_INT_CONVERSION = YES; 155 | CLANG_WARN_UNREACHABLE_CODE = YES; 156 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 157 | COPY_PHASE_STRIP = NO; 158 | ENABLE_STRICT_OBJC_MSGSEND = YES; 159 | GCC_C_LANGUAGE_STANDARD = gnu99; 160 | GCC_DYNAMIC_NO_PIC = NO; 161 | GCC_OPTIMIZATION_LEVEL = 0; 162 | GCC_PREPROCESSOR_DEFINITIONS = ( 163 | "DEBUG=1", 164 | "$(inherited)", 165 | ); 166 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 167 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 168 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 169 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 170 | GCC_WARN_UNDECLARED_SELECTOR = YES; 171 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 172 | GCC_WARN_UNUSED_FUNCTION = YES; 173 | GCC_WARN_UNUSED_VARIABLE = YES; 174 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 175 | ONLY_ACTIVE_ARCH = YES; 176 | SDKROOT = iphoneos; 177 | }; 178 | name = Debug; 179 | }; 180 | 6A5A96B3153FFDF2004EA62B /* Release */ = { 181 | isa = XCBuildConfiguration; 182 | buildSettings = { 183 | ALWAYS_SEARCH_USER_PATHS = NO; 184 | CLANG_ENABLE_OBJC_ARC = YES; 185 | CLANG_WARN_BOOL_CONVERSION = YES; 186 | CLANG_WARN_CONSTANT_CONVERSION = YES; 187 | CLANG_WARN_EMPTY_BODY = YES; 188 | CLANG_WARN_ENUM_CONVERSION = YES; 189 | CLANG_WARN_INT_CONVERSION = YES; 190 | CLANG_WARN_UNREACHABLE_CODE = YES; 191 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 192 | COPY_PHASE_STRIP = YES; 193 | ENABLE_STRICT_OBJC_MSGSEND = YES; 194 | GCC_C_LANGUAGE_STANDARD = gnu99; 195 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 196 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 197 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 198 | GCC_WARN_UNDECLARED_SELECTOR = YES; 199 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 200 | GCC_WARN_UNUSED_FUNCTION = YES; 201 | GCC_WARN_UNUSED_VARIABLE = YES; 202 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 203 | SDKROOT = iphoneos; 204 | VALIDATE_PRODUCT = YES; 205 | }; 206 | name = Release; 207 | }; 208 | 6A5A96B5153FFDF2004EA62B /* Debug */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | DSTROOT = /tmp/NGVaryingGridView.dst; 212 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 213 | GCC_PREFIX_HEADER = "NGVaryingGridView/NGVaryingGridView-Prefix.pch"; 214 | OTHER_LDFLAGS = "-ObjC"; 215 | PRODUCT_NAME = "$(TARGET_NAME)"; 216 | SKIP_INSTALL = YES; 217 | }; 218 | name = Debug; 219 | }; 220 | 6A5A96B6153FFDF2004EA62B /* Release */ = { 221 | isa = XCBuildConfiguration; 222 | buildSettings = { 223 | DSTROOT = /tmp/NGVaryingGridView.dst; 224 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 225 | GCC_PREFIX_HEADER = "NGVaryingGridView/NGVaryingGridView-Prefix.pch"; 226 | OTHER_LDFLAGS = "-ObjC"; 227 | PRODUCT_NAME = "$(TARGET_NAME)"; 228 | SKIP_INSTALL = YES; 229 | }; 230 | name = Release; 231 | }; 232 | /* End XCBuildConfiguration section */ 233 | 234 | /* Begin XCConfigurationList section */ 235 | 6A5A96A1153FFDF2004EA62B /* Build configuration list for PBXProject "NGVaryingGridView" */ = { 236 | isa = XCConfigurationList; 237 | buildConfigurations = ( 238 | 6A5A96B2153FFDF2004EA62B /* Debug */, 239 | 6A5A96B3153FFDF2004EA62B /* Release */, 240 | ); 241 | defaultConfigurationIsVisible = 0; 242 | defaultConfigurationName = Release; 243 | }; 244 | 6A5A96B4153FFDF2004EA62B /* Build configuration list for PBXNativeTarget "NGVaryingGridView" */ = { 245 | isa = XCConfigurationList; 246 | buildConfigurations = ( 247 | 6A5A96B5153FFDF2004EA62B /* Debug */, 248 | 6A5A96B6153FFDF2004EA62B /* Release */, 249 | ); 250 | defaultConfigurationIsVisible = 0; 251 | defaultConfigurationName = Release; 252 | }; 253 | /* End XCConfigurationList section */ 254 | }; 255 | rootObject = 6A5A969E153FFDF2004EA62B /* Project object */; 256 | } 257 | -------------------------------------------------------------------------------- /NGVaryingGridView/NGVaryingGridView/NGVaryingGridView-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'NGVaryingGridView' target in the 'NGVaryingGridView' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /NGVaryingGridView/NGVaryingGridView/NGVaryingGridView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NGVaryingGridView.h 3 | // NGVaryingGridView 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class NGVaryingGridView; 12 | @class NGVaryingGridViewDelegate; 13 | 14 | //////////////////////////////////////////////////////////////////////// 15 | #pragma mark - NGVaryingGridViewDelegate 16 | //////////////////////////////////////////////////////////////////////// 17 | 18 | @protocol NGVaryingGridViewDelegate 19 | 20 | @required 21 | - (NSArray *)rectsForCellsInGridView:(NGVaryingGridView *)gridView; 22 | - (UIView *)gridView:(NGVaryingGridView *)gridView viewForCellWithRect:(CGRect)rect index:(NSUInteger)index; 23 | 24 | @optional 25 | - (void)gridView:(NGVaryingGridView *)gridView didSelectCell:(UIView *)cell index:(NSUInteger)index; 26 | - (void)gridView:(NGVaryingGridView *)gridView willPrepareCellForReuse:(UIView *)cell; 27 | 28 | @end 29 | 30 | //////////////////////////////////////////////////////////////////////// 31 | #pragma mark - NGVaryingGridViewLockPosition 32 | //////////////////////////////////////////////////////////////////////// 33 | 34 | typedef enum { 35 | NGVaryingGridViewLockPositionTop = 0, 36 | NGVaryingGridViewLockPositionLeft 37 | } NGVaryingGridViewLockPosition; 38 | 39 | //////////////////////////////////////////////////////////////////////// 40 | #pragma mark - NGVaryingGridView 41 | //////////////////////////////////////////////////////////////////////// 42 | 43 | @interface NGVaryingGridView : UIView 44 | 45 | @property (nonatomic, unsafe_unretained) id gridViewDelegate; 46 | @property (nonatomic, unsafe_unretained) id scrollViewDelegate; 47 | @property (nonatomic) CGFloat maximumContentWidth; 48 | @property (nonatomic) CGFloat maximumContentHeight; 49 | @property (nonatomic, readonly) CGRect visibleRect; 50 | @property(nonatomic, getter=isDirectionalLockEnabled) BOOL directionalLockEnabled; 51 | @property (nonatomic) BOOL showsHorizontalScrollIndicator; 52 | @property (nonatomic) BOOL showsVerticalScrollIndicator; 53 | @property (nonatomic) UIEdgeInsets contentInset; 54 | @property (nonatomic) CGPoint contentOffset; 55 | @property (nonatomic) CGSize contentSize; 56 | 57 | /** 58 | Reloads the rows and sections of the receiver. 59 | */ 60 | - (void)reloadData; 61 | 62 | /** 63 | Returns the GridCell with a point inside its frame 64 | @param point the point locating the GridCell inside the GridView 65 | @return the GridCell at the given point or `nil` if there is no GridCell at this point or is not loaded. 66 | */ 67 | - (UIView *)gridCellWithCGPoint:(CGPoint)point; 68 | 69 | /** 70 | Scroll the GridView to a specifc GridCell 71 | @param cell the GridCell where the GridView should scroll to 72 | @param animated `YES` if you want to animate the change in position, `NO` if it should be immediate. 73 | */ 74 | - (void)scrollToGridCell:(UIView *)cell animated:(BOOL)animated; 75 | 76 | /** 77 | Scroll the GridView to a specifc Rect 78 | @param rect the CGRect where the GridView should scroll to 79 | @param animated `YES` if you want to animate the change in position, `NO` if it should be immediate. 80 | */ 81 | - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated; 82 | 83 | /** 84 | Adds an Overlay to the GridView. The `UIView` will not be inside the scrollable Area, but above it 85 | @param overlayView the OverlayView 86 | */ 87 | - (void)addOverlayView:(UIView *)overlayView; 88 | 89 | /** 90 | Returns a reusable Cell 91 | @return the GridCell for reuse or `nil` if no reusable Cell is available 92 | */ 93 | - (UIView *)dequeueReusableCell __attribute__((deprecated)); 94 | 95 | /** 96 | Returns a reusable Cell and sets the frame 97 | @param frame the frame of the Cell 98 | @return the GridCell for reuse or `nil` if no reusable Cell is available 99 | */ 100 | - (UIView *)dequeueReusableCellWithFrame:(CGRect)frame; 101 | 102 | /** 103 | Sets a sticky View to the scrollable Area at a specific Lockposition 104 | @param view the sticky View 105 | @param lockPosition a `NGVaryingGridViewLockPosition` which defines the sticky Lockposition 106 | */ 107 | - (void)setStickyView:(UIView *)view lockPosition:(NGVaryingGridViewLockPosition)lockPosition; 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /NGVaryingGridView/NGVaryingGridView/NGVaryingGridView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NGVaryingGridView.m 3 | // NGVaryingGridView 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import "NGVaryingGridView.h" 10 | 11 | @interface NGVaryingGridView () { 12 | BOOL _topStickyViewOnHierarchyTop; 13 | } 14 | 15 | @property (nonatomic, strong) UIScrollView *scrollView; 16 | @property (nonatomic, strong) NSArray *gridRects; 17 | @property (nonatomic, strong) NSMutableDictionary *gridCells; 18 | @property (nonatomic, strong) NSMutableSet *reuseableCells; 19 | 20 | @property (nonatomic, strong) UIView *stickyViewForTopPosition; 21 | @property (nonatomic, strong) UIView *stickyViewForLeftPosition; 22 | @property (nonatomic) CGFloat stickyViewForTopPositionPadding; 23 | @property (nonatomic) CGFloat stickyViewForLeftPositionPadding; 24 | 25 | - (void)loadCellsInRect:(CGRect)rect; 26 | - (void)handleTap:(UIGestureRecognizer *)gestureRecognizer; 27 | - (void)updateStickyViewsPosition; 28 | - (void)bringScrollingIndicatorsToFront; 29 | 30 | @end 31 | 32 | @implementation NGVaryingGridView 33 | 34 | @synthesize scrollViewDelegate = _scrollViewDelegate; 35 | @synthesize gridViewDelegate = _gridViewDelegate; 36 | @synthesize scrollView = _scrollView; 37 | @synthesize gridRects = _gridRects; 38 | @synthesize gridCells = _gridCells; 39 | @synthesize reuseableCells = _reuseableCells; 40 | 41 | @synthesize maximumContentWidth = _maximumContentWidth; 42 | @synthesize maximumContentHeight = _maximumContentHeight; 43 | 44 | @synthesize stickyViewForTopPosition = _stickyViewForTopPosition; 45 | @synthesize stickyViewForLeftPosition = _stickyViewForLeftPosition; 46 | @synthesize stickyViewForLeftPositionPadding = _stickyViewForLeftPositionPadding; 47 | @synthesize stickyViewForTopPositionPadding = _stickyViewForTopPositionPadding; 48 | 49 | //////////////////////////////////////////////////////////////////////// 50 | #pragma mark - Life Cycle 51 | //////////////////////////////////////////////////////////////////////// 52 | 53 | - (id)initWithFrame:(CGRect)frame 54 | { 55 | self = [super initWithFrame:frame]; 56 | if (self) { 57 | _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 58 | _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 59 | _scrollView.directionalLockEnabled = YES; 60 | _gridCells = [NSMutableDictionary dictionary]; 61 | _reuseableCells = [NSMutableSet set]; 62 | _maximumContentHeight = CGFLOAT_MAX; 63 | _maximumContentWidth = CGFLOAT_MAX; 64 | 65 | [super addSubview:_scrollView]; 66 | _scrollView.delegate = self; 67 | } 68 | return self; 69 | } 70 | 71 | - (void)dealloc { 72 | _scrollView.delegate = nil; 73 | } 74 | 75 | //////////////////////////////////////////////////////////////////////// 76 | #pragma mark - UIView 77 | //////////////////////////////////////////////////////////////////////// 78 | 79 | - (void)willMoveToSuperview:(UIView *)newSuperview { 80 | [super willMoveToSuperview:newSuperview]; 81 | if (newSuperview != nil) { 82 | [self reloadData]; 83 | } 84 | } 85 | 86 | - (void)layoutSubviews { 87 | [super layoutSubviews]; 88 | 89 | [self loadCellsInRect:self.visibleRect]; 90 | [self updateStickyViewsPosition]; 91 | [self bringScrollingIndicatorsToFront]; 92 | } 93 | 94 | //////////////////////////////////////////////////////////////////////// 95 | #pragma mark - PVTVGridView 96 | //////////////////////////////////////////////////////////////////////// 97 | 98 | - (void)setGridViewDelegate:(id)gridViewDelegate { 99 | if (gridViewDelegate != _gridViewDelegate) { 100 | _gridViewDelegate = gridViewDelegate; 101 | [self reloadData]; 102 | } 103 | } 104 | 105 | - (void)reloadData { 106 | if (_gridViewDelegate && self.superview != nil) { 107 | CGFloat maxX = 0.f; 108 | CGFloat maxY = 0.f; 109 | 110 | self.gridRects = [self.gridViewDelegate rectsForCellsInGridView:self]; 111 | [self.gridCells.allValues makeObjectsPerformSelector:@selector(removeFromSuperview)]; 112 | [self.reuseableCells addObjectsFromArray:self.gridCells.allValues]; 113 | [self.gridCells removeAllObjects]; 114 | 115 | for (NSValue *rectValue in self.gridRects) { 116 | CGRect rect = [rectValue CGRectValue]; 117 | maxX = MAX(maxX, rect.origin.x + rect.size.width); 118 | maxY = MAX(maxY, rect.origin.y + rect.size.height); 119 | } 120 | maxX = MAX(MIN(maxX, self.maximumContentWidth), self.contentSize.width); 121 | maxY = MAX(MIN(maxY, self.maximumContentHeight), self.contentSize.height); 122 | self.scrollView.contentSize = CGSizeMake(maxX, maxY); 123 | 124 | [self loadCellsInRect:self.visibleRect]; 125 | [self updateStickyViewsPosition]; 126 | } 127 | } 128 | 129 | - (UIView *)gridCellWithCGPoint:(CGPoint)point { 130 | for (UIView *view in self.gridCells.allValues) { 131 | if (CGRectContainsPoint(view.frame, point)) { 132 | return view; 133 | } 134 | } 135 | 136 | return nil; 137 | } 138 | 139 | - (void)addOverlayView:(UIView *)overlayView { 140 | [super addSubview:overlayView]; 141 | } 142 | 143 | - (void)setStickyView:(UIView *)view lockPosition:(NGVaryingGridViewLockPosition)lockPosition { 144 | switch (lockPosition) { 145 | case NGVaryingGridViewLockPositionTop: 146 | [self.stickyViewForTopPosition removeFromSuperview]; 147 | self.stickyViewForTopPositionPadding = view.frame.origin.y; 148 | self.stickyViewForTopPosition = view; 149 | _topStickyViewOnHierarchyTop = YES; 150 | break; 151 | 152 | case NGVaryingGridViewLockPositionLeft: 153 | [self.stickyViewForLeftPosition removeFromSuperview]; 154 | self.stickyViewForLeftPositionPadding = view.frame.origin.x; 155 | self.stickyViewForLeftPosition = view; 156 | _topStickyViewOnHierarchyTop = NO; 157 | break; 158 | 159 | default: 160 | break; 161 | } 162 | 163 | [self.scrollView addSubview:view]; 164 | [self updateStickyViewsPosition]; 165 | } 166 | 167 | //////////////////////////////////////////////////////////////////////// 168 | #pragma mark - PVTVGridView (Private Methods) 169 | //////////////////////////////////////////////////////////////////////// 170 | 171 | - (void)handleTap:(UIGestureRecognizer *)gestureRecognizer { 172 | if ([self.gridViewDelegate respondsToSelector:@selector(gridView:didSelectCell:index:)]) { 173 | [self.gridViewDelegate gridView:self didSelectCell:gestureRecognizer.view index:[self.gridRects indexOfObject:[NSValue valueWithCGRect:gestureRecognizer.view.frame]]]; 174 | } 175 | } 176 | 177 | - (void)loadCellsInRect:(CGRect)rect { 178 | NSUInteger index = 0; 179 | NSMutableDictionary *usedCells = [NSMutableDictionary dictionary]; 180 | for (NSValue *rectValue in self.gridRects) { 181 | CGRect rectOfValue = [rectValue CGRectValue]; 182 | if (!CGRectIsEmpty(CGRectIntersection(rect, rectOfValue))) { 183 | UIView *gridViewCell = [self.gridCells objectForKey:rectValue]; 184 | if (gridViewCell == nil) { 185 | gridViewCell = [self.gridViewDelegate gridView:self viewForCellWithRect:rectOfValue index:index]; 186 | gridViewCell.userInteractionEnabled = YES; 187 | [gridViewCell addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]]; 188 | [self.gridCells setObject:gridViewCell forKey:rectValue]; 189 | } 190 | 191 | [usedCells setObject:gridViewCell forKey:rectValue]; 192 | [self.scrollView addSubview:gridViewCell]; 193 | } 194 | index ++; 195 | } 196 | 197 | // Move unused Cells to reusableCells 198 | NSMutableDictionary *unusedCells = [NSMutableDictionary dictionaryWithDictionary:self.gridCells]; 199 | [unusedCells removeObjectsForKeys:usedCells.allKeys]; 200 | [unusedCells.allValues makeObjectsPerformSelector:@selector(removeFromSuperview)]; 201 | 202 | [self.gridCells removeObjectsForKeys:unusedCells.allKeys]; 203 | [self.reuseableCells addObjectsFromArray:unusedCells.allValues]; 204 | } 205 | 206 | - (UIView *)dequeueReusableCell { 207 | return [self dequeueReusableCellWithFrame:CGRectZero]; 208 | } 209 | 210 | - (UIView *)dequeueReusableCellWithFrame:(CGRect)frame { 211 | UIView *reusableCell = [self.reuseableCells anyObject]; 212 | if (reusableCell) { 213 | if ([self.gridViewDelegate respondsToSelector:@selector(gridView:willPrepareCellForReuse:)]) { 214 | [self.gridViewDelegate gridView:self willPrepareCellForReuse:reusableCell]; 215 | } 216 | [self.reuseableCells removeObject:reusableCell]; 217 | } 218 | reusableCell.frame = frame; 219 | return reusableCell; 220 | } 221 | 222 | - (void)updateStickyViewsPosition { 223 | self.stickyViewForTopPosition.frame = CGRectMake(self.stickyViewForTopPosition.frame.origin.x, self.scrollView.contentOffset.y + self.stickyViewForTopPositionPadding, self.stickyViewForTopPosition.frame.size.width, self.stickyViewForTopPosition.frame.size.height); 224 | self.stickyViewForLeftPosition.frame = CGRectMake(self.scrollView.contentOffset.x + self.stickyViewForLeftPositionPadding, self.stickyViewForLeftPosition.frame.origin.y, self.stickyViewForLeftPosition.frame.size.width, self.stickyViewForLeftPosition.frame.size.height); 225 | 226 | if (_topStickyViewOnHierarchyTop) { 227 | [self.scrollView bringSubviewToFront:self.stickyViewForLeftPosition]; 228 | [self.scrollView bringSubviewToFront:self.stickyViewForTopPosition]; 229 | } else { 230 | [self.scrollView bringSubviewToFront:self.stickyViewForTopPosition]; 231 | [self.scrollView bringSubviewToFront:self.stickyViewForLeftPosition]; 232 | } 233 | } 234 | 235 | - (void)bringScrollingIndicatorsToFront { 236 | // ScrollIndicator will hide underneath view when you are adding Subviews while Scrolling 237 | if (self.showsHorizontalScrollIndicator) { 238 | self.scrollView.showsHorizontalScrollIndicator = NO; 239 | self.scrollView.showsHorizontalScrollIndicator = YES; 240 | } 241 | 242 | if (self.showsVerticalScrollIndicator) { 243 | self.scrollView.showsVerticalScrollIndicator = NO; 244 | self.scrollView.showsVerticalScrollIndicator = YES; 245 | } 246 | } 247 | 248 | //////////////////////////////////////////////////////////////////////// 249 | #pragma mark - UIScrolLView Forwarding 250 | //////////////////////////////////////////////////////////////////////// 251 | 252 | - (void)scrollToGridCell:(UIView *)cell animated:(BOOL)animated { 253 | [self.scrollView scrollRectToVisible:cell.frame animated:animated]; 254 | } 255 | 256 | - (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated { 257 | [self.scrollView scrollRectToVisible:rect animated:animated]; 258 | } 259 | 260 | - (CGRect)visibleRect { 261 | CGRect visibleRect; 262 | visibleRect.origin = self.scrollView.contentOffset; 263 | visibleRect.size = self.scrollView.bounds.size; 264 | 265 | float scale = 1.0 / self.scrollView.zoomScale; 266 | visibleRect.origin.x *= scale; 267 | visibleRect.origin.y *= scale; 268 | visibleRect.size.width *= scale; 269 | visibleRect.size.height *= scale; 270 | 271 | return visibleRect; 272 | } 273 | 274 | - (void)addSubview:(UIView *)view { 275 | [self.scrollView addSubview:view]; 276 | } 277 | 278 | - (BOOL)isDirectionalLockEnabled { 279 | return self.scrollView.isDirectionalLockEnabled; 280 | } 281 | 282 | - (void)setDirectionalLockEnabled:(BOOL)directionalLockEnabled { 283 | self.scrollView.directionalLockEnabled = directionalLockEnabled; 284 | } 285 | 286 | - (void)setShowsVerticalScrollIndicator:(BOOL)showsVerticalScrollIndicator { 287 | self.scrollView.showsVerticalScrollIndicator = showsVerticalScrollIndicator; 288 | } 289 | 290 | - (BOOL)showsVerticalScrollIndicator { 291 | return self.scrollView.showsVerticalScrollIndicator; 292 | } 293 | 294 | - (void)setShowsHorizontalScrollIndicator:(BOOL)showsHorizontalScrollIndicator { 295 | self.scrollView.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator; 296 | } 297 | 298 | - (BOOL)showsHorizontalScrollIndicator { 299 | return self.scrollView.showsHorizontalScrollIndicator; 300 | } 301 | 302 | - (void)setContentInset:(UIEdgeInsets)contentInset { 303 | self.scrollView.contentInset = contentInset; 304 | } 305 | 306 | - (UIEdgeInsets)contentInset { 307 | return self.scrollView.contentInset; 308 | } 309 | 310 | - (void)setContentOffset:(CGPoint)contentOffset { 311 | self.scrollView.contentOffset = contentOffset; 312 | } 313 | 314 | - (CGPoint)contentOffset { 315 | return self.scrollView.contentOffset; 316 | } 317 | 318 | - (void)setContentSize:(CGSize)contentSize { 319 | self.scrollView.contentSize = contentSize; 320 | } 321 | 322 | - (CGSize)contentSize { 323 | return self.scrollView.contentSize; 324 | } 325 | 326 | //////////////////////////////////////////////////////////////////////// 327 | #pragma mark - UIScrollViewDelegate 328 | //////////////////////////////////////////////////////////////////////// 329 | 330 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 331 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) { 332 | [self.scrollViewDelegate scrollViewDidScroll:scrollView]; 333 | } 334 | 335 | [self loadCellsInRect:self.visibleRect]; 336 | [self updateStickyViewsPosition]; 337 | [self bringScrollingIndicatorsToFront]; 338 | } 339 | - (void)scrollViewDidZoom:(UIScrollView *)scrollView { 340 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidZoom:)]) { 341 | [self.scrollViewDelegate scrollViewDidZoom:scrollView]; 342 | } 343 | } 344 | 345 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 346 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) { 347 | [self.scrollViewDelegate scrollViewWillBeginDragging:scrollView]; 348 | } 349 | } 350 | 351 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { 352 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) { 353 | [self.scrollViewDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset]; 354 | } 355 | } 356 | 357 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 358 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) { 359 | [self.scrollViewDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; 360 | } 361 | } 362 | 363 | - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { 364 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) { 365 | [self.scrollViewDelegate scrollViewWillBeginDecelerating:scrollView]; 366 | } 367 | } 368 | 369 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 370 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) { 371 | [self.scrollViewDelegate scrollViewDidEndDecelerating:scrollView]; 372 | } 373 | } 374 | 375 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { 376 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) { 377 | [self.scrollViewDelegate scrollViewDidEndScrollingAnimation:scrollView]; 378 | } 379 | } 380 | 381 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { 382 | if ([self.scrollViewDelegate respondsToSelector:@selector(viewForZoomingInScrollView:)]) { 383 | return [self.scrollViewDelegate viewForZoomingInScrollView:scrollView]; 384 | } 385 | return nil; 386 | } 387 | 388 | - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { 389 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewWillBeginZooming:withView:)]) { 390 | [self.scrollViewDelegate scrollViewWillBeginZooming:scrollView withView:view]; 391 | } 392 | } 393 | 394 | - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale { 395 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndZooming:withView:atScale:)]) { 396 | [self.scrollViewDelegate scrollViewDidEndZooming:scrollView withView:view atScale:scale]; 397 | } 398 | } 399 | 400 | - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView { 401 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) { 402 | return [self.scrollViewDelegate scrollViewShouldScrollToTop:scrollView]; 403 | } 404 | return YES; 405 | } 406 | 407 | - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView { 408 | if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidScrollToTop:)]) { 409 | [self.scrollViewDelegate scrollViewDidScrollToTop:scrollView]; 410 | } 411 | } 412 | 413 | @end 414 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6ABB7F37154080A700334EF3 /* libNGVaryingGridView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6ABB7F2A1540808800334EF3 /* libNGVaryingGridView.a */; }; 11 | 6ABB7F61154096F000334EF3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6ABB7F60154096F000334EF3 /* QuartzCore.framework */; }; 12 | 6ABB7F64154099D900334EF3 /* NGTimeTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6ABB7F63154099D900334EF3 /* NGTimeTableCell.m */; }; 13 | 6AFFF67D15407F7800AA8C77 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6AFFF67C15407F7800AA8C77 /* UIKit.framework */; }; 14 | 6AFFF67F15407F7800AA8C77 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6AFFF67E15407F7800AA8C77 /* Foundation.framework */; }; 15 | 6AFFF68115407F7800AA8C77 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6AFFF68015407F7800AA8C77 /* CoreGraphics.framework */; }; 16 | 6AFFF68715407F7800AA8C77 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6AFFF68515407F7800AA8C77 /* InfoPlist.strings */; }; 17 | 6AFFF68915407F7800AA8C77 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AFFF68815407F7800AA8C77 /* main.m */; }; 18 | 6AFFF68D15407F7800AA8C77 /* NGAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AFFF68C15407F7800AA8C77 /* NGAppDelegate.m */; }; 19 | 6AFFF69015407F7800AA8C77 /* NGViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AFFF68F15407F7800AA8C77 /* NGViewController.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 6ABB7F291540808800334EF3 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 6ABB7F251540808800334EF3 /* NGVaryingGridView.xcodeproj */; 26 | proxyType = 2; 27 | remoteGlobalIDString = 6A5A96A7153FFDF2004EA62B; 28 | remoteInfo = NGVaryingGridView; 29 | }; 30 | 6ABB7F35154080A300334EF3 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 6ABB7F251540808800334EF3 /* NGVaryingGridView.xcodeproj */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 6A5A96A6153FFDF2004EA62B; 35 | remoteInfo = NGVaryingGridView; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 6ABB7F251540808800334EF3 /* NGVaryingGridView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = NGVaryingGridView.xcodeproj; path = ../NGVaryingGridView/NGVaryingGridView.xcodeproj; sourceTree = ""; }; 41 | 6ABB7F60154096F000334EF3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 42 | 6ABB7F62154099D900334EF3 /* NGTimeTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NGTimeTableCell.h; sourceTree = ""; }; 43 | 6ABB7F63154099D900334EF3 /* NGTimeTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NGTimeTableCell.m; sourceTree = ""; }; 44 | 6AFFF67815407F7800AA8C77 /* NGVaryingGridViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NGVaryingGridViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 6AFFF67C15407F7800AA8C77 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 46 | 6AFFF67E15407F7800AA8C77 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 47 | 6AFFF68015407F7800AA8C77 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 48 | 6AFFF68415407F7800AA8C77 /* NGVaryingGridViewDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NGVaryingGridViewDemo-Info.plist"; sourceTree = ""; }; 49 | 6AFFF68615407F7800AA8C77 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 50 | 6AFFF68815407F7800AA8C77 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 51 | 6AFFF68A15407F7800AA8C77 /* NGVaryingGridViewDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NGVaryingGridViewDemo-Prefix.pch"; sourceTree = ""; }; 52 | 6AFFF68B15407F7800AA8C77 /* NGAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NGAppDelegate.h; sourceTree = ""; }; 53 | 6AFFF68C15407F7800AA8C77 /* NGAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NGAppDelegate.m; sourceTree = ""; }; 54 | 6AFFF68E15407F7800AA8C77 /* NGViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NGViewController.h; sourceTree = ""; }; 55 | 6AFFF68F15407F7800AA8C77 /* NGViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NGViewController.m; sourceTree = ""; }; 56 | /* End PBXFileReference section */ 57 | 58 | /* Begin PBXFrameworksBuildPhase section */ 59 | 6AFFF67515407F7800AA8C77 /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | 6ABB7F37154080A700334EF3 /* libNGVaryingGridView.a in Frameworks */, 64 | 6AFFF67D15407F7800AA8C77 /* UIKit.framework in Frameworks */, 65 | 6AFFF67F15407F7800AA8C77 /* Foundation.framework in Frameworks */, 66 | 6AFFF68115407F7800AA8C77 /* CoreGraphics.framework in Frameworks */, 67 | 6ABB7F61154096F000334EF3 /* QuartzCore.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | /* End PBXFrameworksBuildPhase section */ 72 | 73 | /* Begin PBXGroup section */ 74 | 6ABB7F261540808800334EF3 /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 6ABB7F2A1540808800334EF3 /* libNGVaryingGridView.a */, 78 | ); 79 | name = Products; 80 | sourceTree = ""; 81 | }; 82 | 6AFFF66D15407F7800AA8C77 = { 83 | isa = PBXGroup; 84 | children = ( 85 | 6AFFF68215407F7800AA8C77 /* NGVaryingGridViewDemo */, 86 | 6AFFF67B15407F7800AA8C77 /* Frameworks */, 87 | 6AFFF67915407F7800AA8C77 /* Products */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | 6AFFF67915407F7800AA8C77 /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 6AFFF67815407F7800AA8C77 /* NGVaryingGridViewDemo.app */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 6AFFF67B15407F7800AA8C77 /* Frameworks */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 6ABB7F251540808800334EF3 /* NGVaryingGridView.xcodeproj */, 103 | 6AFFF67C15407F7800AA8C77 /* UIKit.framework */, 104 | 6AFFF67E15407F7800AA8C77 /* Foundation.framework */, 105 | 6AFFF68015407F7800AA8C77 /* CoreGraphics.framework */, 106 | 6ABB7F60154096F000334EF3 /* QuartzCore.framework */, 107 | ); 108 | name = Frameworks; 109 | sourceTree = ""; 110 | }; 111 | 6AFFF68215407F7800AA8C77 /* NGVaryingGridViewDemo */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 6AFFF68B15407F7800AA8C77 /* NGAppDelegate.h */, 115 | 6AFFF68C15407F7800AA8C77 /* NGAppDelegate.m */, 116 | 6AFFF68E15407F7800AA8C77 /* NGViewController.h */, 117 | 6AFFF68F15407F7800AA8C77 /* NGViewController.m */, 118 | 6AFFF68315407F7800AA8C77 /* Supporting Files */, 119 | 6ABB7F62154099D900334EF3 /* NGTimeTableCell.h */, 120 | 6ABB7F63154099D900334EF3 /* NGTimeTableCell.m */, 121 | ); 122 | path = NGVaryingGridViewDemo; 123 | sourceTree = ""; 124 | }; 125 | 6AFFF68315407F7800AA8C77 /* Supporting Files */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 6AFFF68415407F7800AA8C77 /* NGVaryingGridViewDemo-Info.plist */, 129 | 6AFFF68515407F7800AA8C77 /* InfoPlist.strings */, 130 | 6AFFF68815407F7800AA8C77 /* main.m */, 131 | 6AFFF68A15407F7800AA8C77 /* NGVaryingGridViewDemo-Prefix.pch */, 132 | ); 133 | name = "Supporting Files"; 134 | sourceTree = ""; 135 | }; 136 | /* End PBXGroup section */ 137 | 138 | /* Begin PBXNativeTarget section */ 139 | 6AFFF67715407F7800AA8C77 /* NGVaryingGridViewDemo */ = { 140 | isa = PBXNativeTarget; 141 | buildConfigurationList = 6AFFF69915407F7800AA8C77 /* Build configuration list for PBXNativeTarget "NGVaryingGridViewDemo" */; 142 | buildPhases = ( 143 | 6AFFF67415407F7800AA8C77 /* Sources */, 144 | 6AFFF67515407F7800AA8C77 /* Frameworks */, 145 | 6AFFF67615407F7800AA8C77 /* Resources */, 146 | ); 147 | buildRules = ( 148 | ); 149 | dependencies = ( 150 | 6ABB7F36154080A300334EF3 /* PBXTargetDependency */, 151 | ); 152 | name = NGVaryingGridViewDemo; 153 | productName = NGVaryingGridViewDemo; 154 | productReference = 6AFFF67815407F7800AA8C77 /* NGVaryingGridViewDemo.app */; 155 | productType = "com.apple.product-type.application"; 156 | }; 157 | /* End PBXNativeTarget section */ 158 | 159 | /* Begin PBXProject section */ 160 | 6AFFF66F15407F7800AA8C77 /* Project object */ = { 161 | isa = PBXProject; 162 | attributes = { 163 | CLASSPREFIX = NG; 164 | LastUpgradeCheck = 0430; 165 | ORGANIZATIONNAME = "NOUS Wissensmanagement GmbH"; 166 | }; 167 | buildConfigurationList = 6AFFF67215407F7800AA8C77 /* Build configuration list for PBXProject "NGVaryingGridViewDemo" */; 168 | compatibilityVersion = "Xcode 3.2"; 169 | developmentRegion = English; 170 | hasScannedForEncodings = 0; 171 | knownRegions = ( 172 | en, 173 | ); 174 | mainGroup = 6AFFF66D15407F7800AA8C77; 175 | productRefGroup = 6AFFF67915407F7800AA8C77 /* Products */; 176 | projectDirPath = ""; 177 | projectReferences = ( 178 | { 179 | ProductGroup = 6ABB7F261540808800334EF3 /* Products */; 180 | ProjectRef = 6ABB7F251540808800334EF3 /* NGVaryingGridView.xcodeproj */; 181 | }, 182 | ); 183 | projectRoot = ""; 184 | targets = ( 185 | 6AFFF67715407F7800AA8C77 /* NGVaryingGridViewDemo */, 186 | ); 187 | }; 188 | /* End PBXProject section */ 189 | 190 | /* Begin PBXReferenceProxy section */ 191 | 6ABB7F2A1540808800334EF3 /* libNGVaryingGridView.a */ = { 192 | isa = PBXReferenceProxy; 193 | fileType = archive.ar; 194 | path = libNGVaryingGridView.a; 195 | remoteRef = 6ABB7F291540808800334EF3 /* PBXContainerItemProxy */; 196 | sourceTree = BUILT_PRODUCTS_DIR; 197 | }; 198 | /* End PBXReferenceProxy section */ 199 | 200 | /* Begin PBXResourcesBuildPhase section */ 201 | 6AFFF67615407F7800AA8C77 /* Resources */ = { 202 | isa = PBXResourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | 6AFFF68715407F7800AA8C77 /* InfoPlist.strings in Resources */, 206 | ); 207 | runOnlyForDeploymentPostprocessing = 0; 208 | }; 209 | /* End PBXResourcesBuildPhase section */ 210 | 211 | /* Begin PBXSourcesBuildPhase section */ 212 | 6AFFF67415407F7800AA8C77 /* Sources */ = { 213 | isa = PBXSourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | 6AFFF68915407F7800AA8C77 /* main.m in Sources */, 217 | 6AFFF68D15407F7800AA8C77 /* NGAppDelegate.m in Sources */, 218 | 6AFFF69015407F7800AA8C77 /* NGViewController.m in Sources */, 219 | 6ABB7F64154099D900334EF3 /* NGTimeTableCell.m in Sources */, 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXSourcesBuildPhase section */ 224 | 225 | /* Begin PBXTargetDependency section */ 226 | 6ABB7F36154080A300334EF3 /* PBXTargetDependency */ = { 227 | isa = PBXTargetDependency; 228 | name = NGVaryingGridView; 229 | targetProxy = 6ABB7F35154080A300334EF3 /* PBXContainerItemProxy */; 230 | }; 231 | /* End PBXTargetDependency section */ 232 | 233 | /* Begin PBXVariantGroup section */ 234 | 6AFFF68515407F7800AA8C77 /* InfoPlist.strings */ = { 235 | isa = PBXVariantGroup; 236 | children = ( 237 | 6AFFF68615407F7800AA8C77 /* en */, 238 | ); 239 | name = InfoPlist.strings; 240 | sourceTree = ""; 241 | }; 242 | /* End PBXVariantGroup section */ 243 | 244 | /* Begin XCBuildConfiguration section */ 245 | 6AFFF69715407F7800AA8C77 /* Debug */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | ALWAYS_SEARCH_USER_PATHS = NO; 249 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 250 | CLANG_ENABLE_OBJC_ARC = YES; 251 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 252 | COPY_PHASE_STRIP = NO; 253 | GCC_C_LANGUAGE_STANDARD = gnu99; 254 | GCC_DYNAMIC_NO_PIC = NO; 255 | GCC_OPTIMIZATION_LEVEL = 0; 256 | GCC_PREPROCESSOR_DEFINITIONS = ( 257 | "DEBUG=1", 258 | "$(inherited)", 259 | ); 260 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 261 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 262 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 263 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 264 | GCC_WARN_UNUSED_VARIABLE = YES; 265 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 266 | SDKROOT = iphoneos; 267 | TARGETED_DEVICE_FAMILY = "1,2"; 268 | }; 269 | name = Debug; 270 | }; 271 | 6AFFF69815407F7800AA8C77 /* Release */ = { 272 | isa = XCBuildConfiguration; 273 | buildSettings = { 274 | ALWAYS_SEARCH_USER_PATHS = NO; 275 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 276 | CLANG_ENABLE_OBJC_ARC = YES; 277 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 278 | COPY_PHASE_STRIP = YES; 279 | GCC_C_LANGUAGE_STANDARD = gnu99; 280 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 282 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 283 | GCC_WARN_UNUSED_VARIABLE = YES; 284 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 285 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 286 | SDKROOT = iphoneos; 287 | TARGETED_DEVICE_FAMILY = "1,2"; 288 | VALIDATE_PRODUCT = YES; 289 | }; 290 | name = Release; 291 | }; 292 | 6AFFF69A15407F7800AA8C77 /* Debug */ = { 293 | isa = XCBuildConfiguration; 294 | buildSettings = { 295 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 296 | GCC_PREFIX_HEADER = "NGVaryingGridViewDemo/NGVaryingGridViewDemo-Prefix.pch"; 297 | HEADER_SEARCH_PATHS = "../NGVaryingGridView/**"; 298 | INFOPLIST_FILE = "NGVaryingGridViewDemo/NGVaryingGridViewDemo-Info.plist"; 299 | PRODUCT_NAME = "$(TARGET_NAME)"; 300 | WRAPPER_EXTENSION = app; 301 | }; 302 | name = Debug; 303 | }; 304 | 6AFFF69B15407F7800AA8C77 /* Release */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 308 | GCC_PREFIX_HEADER = "NGVaryingGridViewDemo/NGVaryingGridViewDemo-Prefix.pch"; 309 | HEADER_SEARCH_PATHS = "../NGVaryingGridView/**"; 310 | INFOPLIST_FILE = "NGVaryingGridViewDemo/NGVaryingGridViewDemo-Info.plist"; 311 | PRODUCT_NAME = "$(TARGET_NAME)"; 312 | WRAPPER_EXTENSION = app; 313 | }; 314 | name = Release; 315 | }; 316 | /* End XCBuildConfiguration section */ 317 | 318 | /* Begin XCConfigurationList section */ 319 | 6AFFF67215407F7800AA8C77 /* Build configuration list for PBXProject "NGVaryingGridViewDemo" */ = { 320 | isa = XCConfigurationList; 321 | buildConfigurations = ( 322 | 6AFFF69715407F7800AA8C77 /* Debug */, 323 | 6AFFF69815407F7800AA8C77 /* Release */, 324 | ); 325 | defaultConfigurationIsVisible = 0; 326 | defaultConfigurationName = Release; 327 | }; 328 | 6AFFF69915407F7800AA8C77 /* Build configuration list for PBXNativeTarget "NGVaryingGridViewDemo" */ = { 329 | isa = XCConfigurationList; 330 | buildConfigurations = ( 331 | 6AFFF69A15407F7800AA8C77 /* Debug */, 332 | 6AFFF69B15407F7800AA8C77 /* Release */, 333 | ); 334 | defaultConfigurationIsVisible = 0; 335 | defaultConfigurationName = Release; 336 | }; 337 | /* End XCConfigurationList section */ 338 | }; 339 | rootObject = 6AFFF66F15407F7800AA8C77 /* Project object */; 340 | } 341 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/NGAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // NGAppDelegate.h 3 | // NGVaryingGridViewDemo 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class NGViewController; 12 | 13 | @interface NGAppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) NGViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/NGAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // NGAppDelegate.m 3 | // NGVaryingGridViewDemo 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import "NGAppDelegate.h" 10 | 11 | #import "NGViewController.h" 12 | 13 | @implementation NGAppDelegate 14 | 15 | @synthesize window = _window; 16 | @synthesize viewController = _viewController; 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 21 | self.viewController = [[NGViewController alloc] initWithNibName:nil bundle:nil]; 22 | self.window.rootViewController = self.viewController; 23 | [self.window makeKeyAndVisible]; 24 | return YES; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/NGTimeTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // NGTimeTableCell.h 3 | // NGVaryingGridViewDemo 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NGTimeTableCell : UILabel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/NGTimeTableCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // NGTimeTableCell.m 3 | // NGVaryingGridViewDemo 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import "NGTimeTableCell.h" 10 | 11 | @implementation NGTimeTableCell 12 | 13 | - (id)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | self.textAlignment = UITextAlignmentCenter; 18 | self.backgroundColor = [UIColor redColor]; 19 | self.textColor = [UIColor whiteColor]; 20 | self.font = [UIFont systemFontOfSize:11.f]; 21 | self.numberOfLines = 0; 22 | self.lineBreakMode = UILineBreakModeWordWrap; 23 | CALayer *layer = self.layer; 24 | layer.cornerRadius = 5.f; 25 | layer.masksToBounds = YES; 26 | layer.borderWidth = 1.f; 27 | layer.borderColor = [[UIColor darkGrayColor] CGColor]; 28 | 29 | } 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/NGVaryingGridViewDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.nousguide.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/NGVaryingGridViewDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'NGVaryingGridViewDemo' target in the 'NGVaryingGridViewDemo' 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 | #import 15 | #endif 16 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/NGViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NGViewController.h 3 | // NGVaryingGridViewDemo 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NGViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/NGViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NGViewController.m 3 | // NGVaryingGridViewDemo 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import "NGViewController.h" 10 | #import "NGVaryingGridView.h" 11 | #import "NGTimeTableCell.h" 12 | 13 | #define kColumnWidth ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad ? 200.f : 100.f) 14 | #define kRightPadding ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad ? 91.f : 46.f) 15 | #define kContentHeight ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad ? 1600.f : 800.f) 16 | 17 | @interface NGViewController () 18 | 19 | @property (nonatomic, strong) NGVaryingGridView *gridView; 20 | @property (nonatomic, strong) NSMutableArray *events; 21 | 22 | @end 23 | 24 | @implementation NGViewController 25 | 26 | @synthesize gridView = _gridView; 27 | @synthesize events = _events; 28 | 29 | //////////////////////////////////////////////////////////////////////// 30 | #pragma mark - Life Cycle 31 | //////////////////////////////////////////////////////////////////////// 32 | 33 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 34 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 35 | _events = [NSArray arrayWithObjects: 36 | [NSDictionary dictionaryWithObjectsAndKeys: 37 | [NSNumber numberWithFloat:1.5f], @"begin", 38 | [NSNumber numberWithFloat:0.75f], @"duration", 39 | [NSNumber numberWithInt:0], @"day", 40 | @"08:30 Programming Language Lecture", @"title", nil], 41 | [NSDictionary dictionaryWithObjectsAndKeys: 42 | [NSNumber numberWithFloat:4.f], @"begin", 43 | [NSNumber numberWithFloat:2.5f], @"duration", 44 | [NSNumber numberWithInt:0], @"day", 45 | @"11:00 Workout", @"title", nil], 46 | [NSDictionary dictionaryWithObjectsAndKeys: 47 | [NSNumber numberWithFloat:4.5f], @"begin", 48 | [NSNumber numberWithFloat:0.5f], @"duration", 49 | [NSNumber numberWithInt:1], @"day", 50 | @"12:30 Brunch with Lisa", @"title", nil], 51 | [NSDictionary dictionaryWithObjectsAndKeys: 52 | [NSNumber numberWithFloat:2.f], @"begin", 53 | [NSNumber numberWithFloat:4.5f], @"duration", 54 | [NSNumber numberWithInt:2], @"day", 55 | @"09:00 @Work", @"title", nil], 56 | [NSDictionary dictionaryWithObjectsAndKeys: 57 | [NSNumber numberWithFloat:1.f], @"begin", 58 | [NSNumber numberWithFloat:2.f], @"duration", 59 | [NSNumber numberWithInt:4], @"day", 60 | @"08:00 Security Lecture", @"title", nil], 61 | nil]; 62 | } 63 | 64 | return self; 65 | } 66 | 67 | //////////////////////////////////////////////////////////////////////// 68 | #pragma mark - UIViewController 69 | //////////////////////////////////////////////////////////////////////// 70 | 71 | - (void)viewDidLoad { 72 | [super viewDidLoad]; 73 | self.view.backgroundColor = [UIColor whiteColor]; 74 | 75 | self.gridView = [[NGVaryingGridView alloc] initWithFrame:self.view.bounds]; 76 | self.gridView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 77 | self.gridView.gridViewDelegate = self; 78 | [self.view addSubview:self.gridView]; 79 | 80 | UIView *timeLine = [[UIView alloc] initWithFrame:CGRectMake(-1.f, -600.f, kRightPadding + 1.f, kContentHeight + 600.f)]; 81 | CALayer *layer = timeLine.layer; 82 | layer.masksToBounds = NO; 83 | layer.borderWidth = 1.f; 84 | layer.borderColor = [[UIColor blackColor] CGColor]; 85 | layer.shadowOffset = CGSizeMake(5.f, 0.f); 86 | layer.shadowRadius = 5.f; 87 | layer.shadowOpacity = 0.5f; 88 | 89 | timeLine.backgroundColor = [UIColor grayColor]; 90 | for (int i = 0; i < 7; i++) { 91 | UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.f, 600.f + kContentHeight / 8.f * (i+1), timeLine.frame.size.width, 40.f)]; 92 | timeLabel.backgroundColor = [UIColor clearColor]; 93 | timeLabel.textColor = [UIColor whiteColor]; 94 | timeLabel.textAlignment = UITextAlignmentCenter; 95 | timeLabel.text = [NSString stringWithFormat:@"%02d:00", i+8]; 96 | timeLabel.font = [UIFont boldSystemFontOfSize:12.f]; 97 | timeLabel.shadowColor = [UIColor darkGrayColor]; 98 | timeLabel.shadowOffset = CGSizeMake(1.f, 1.f); 99 | [timeLine addSubview:timeLabel]; 100 | } 101 | 102 | UIView *dayLine = [[UIView alloc] initWithFrame:CGRectMake(-600.f, -1.f, kColumnWidth * 5.f + kRightPadding + 1200.f, kContentHeight / 8.f)]; 103 | dayLine.backgroundColor = [UIColor grayColor]; 104 | layer = dayLine.layer; 105 | layer.masksToBounds = NO; 106 | layer.borderWidth = 1.f; 107 | layer.borderColor = [[UIColor blackColor] CGColor]; 108 | layer.shadowOffset = CGSizeMake(5.f, 0.f); 109 | layer.shadowRadius = 5.f; 110 | layer.shadowOpacity = 0.5f; 111 | 112 | UIView *grayView = [[UIView alloc] initWithFrame:CGRectMake(-600.f, dayLine.frame.size.height / 2.f, dayLine.frame.size.width + 1200.f, dayLine.frame.size.height / 2.f)]; 113 | grayView.backgroundColor = [UIColor lightGrayColor]; 114 | layer = grayView.layer; 115 | layer.masksToBounds = NO; 116 | layer.borderWidth = 1.f; 117 | layer.borderColor = [[UIColor blackColor] CGColor]; 118 | [dayLine addSubview:grayView]; 119 | NSArray *days = [NSArray arrayWithObjects:@"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", nil]; 120 | for (int i = 0; i < 5; i++) { 121 | UILabel *dayLabel = [[UILabel alloc] initWithFrame:CGRectMake(i * kColumnWidth + timeLine.frame.size.width + 600.f, 0.f, kColumnWidth, grayView.frame.size.height)]; 122 | dayLabel.backgroundColor = [UIColor clearColor]; 123 | dayLabel.textColor = [UIColor whiteColor]; 124 | dayLabel.textAlignment = UITextAlignmentCenter; 125 | dayLabel.text = [days objectAtIndex:i]; 126 | dayLabel.font = [UIFont boldSystemFontOfSize:12.f]; 127 | dayLabel.shadowColor = [UIColor darkGrayColor]; 128 | dayLabel.shadowOffset = CGSizeMake(1.f, 1.f); 129 | [dayLine addSubview:dayLabel]; 130 | } 131 | 132 | NGTimeTableCell *wholeDayEvent = [[NGTimeTableCell alloc] initWithFrame:CGRectMake(600.f + kRightPadding + 0 * kColumnWidth + 5.f, kContentHeight / 16.f + 5.f, 2 * kColumnWidth - 10.f, kContentHeight / 16.f - 10.f)]; 133 | wholeDayEvent.backgroundColor = [UIColor blueColor]; 134 | wholeDayEvent.text = @"Vacation"; 135 | [dayLine addSubview:wholeDayEvent]; 136 | 137 | [self.gridView setStickyView:dayLine lockPosition:NGVaryingGridViewLockPositionTop]; 138 | [self.gridView setStickyView:timeLine lockPosition:NGVaryingGridViewLockPositionLeft]; 139 | 140 | [self.gridView reloadData]; 141 | } 142 | 143 | - (void)viewDidUnload { 144 | [super viewDidUnload]; 145 | self.gridView.gridViewDelegate = nil; 146 | self.gridView = nil; 147 | } 148 | 149 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 150 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 151 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 152 | } else { 153 | return YES; 154 | } 155 | } 156 | 157 | //////////////////////////////////////////////////////////////////////// 158 | #pragma mark - NGVaryingGridViewDelegate 159 | //////////////////////////////////////////////////////////////////////// 160 | 161 | - (NSArray *)rectsForCellsInGridView:(NGVaryingGridView *)gridView { 162 | NSMutableArray *rectsArray = [NSMutableArray array]; 163 | for (NSDictionary *event in self.events) { 164 | [rectsArray addObject:[NSValue valueWithCGRect:CGRectMake(kRightPadding + 5.f + [[event objectForKey:@"day"] floatValue] * kColumnWidth, [[event objectForKey:@"begin"] floatValue] * kContentHeight / 8 + 5.f, kColumnWidth - 10.f, [[event objectForKey:@"duration"] floatValue] * kContentHeight / 8 - 10.f)]]; 165 | } 166 | return rectsArray; 167 | } 168 | 169 | - (UIView *)gridView:(NGVaryingGridView *)gridView viewForCellWithRect:(CGRect)rect index:(NSUInteger)index { 170 | NGTimeTableCell *cell = (NGTimeTableCell *) ([gridView dequeueReusableCellWithFrame:rect] ?: [[NGTimeTableCell alloc] initWithFrame:rect]); 171 | 172 | NSDictionary *event = [self.events objectAtIndex:index]; 173 | cell.text = [event objectForKey:@"title"]; 174 | return cell; 175 | } 176 | 177 | - (void)gridView:(NGVaryingGridView *)gridView didSelectCell:(UIView *)cell index:(NSUInteger)index { 178 | NSLog(@"You selected a cell!"); 179 | } 180 | 181 | - (void)gridView:(NGVaryingGridView *)gridView willPrepareCellForReuse:(UIView *)cell { 182 | 183 | } 184 | 185 | @end 186 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /NGVaryingGridViewDemo/NGVaryingGridViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // NGVaryingGridViewDemo 4 | // 5 | // Created by Philip Messlehner on 19.04.12. 6 | // Copyright (c) 2012 NOUS Wissensmanagement GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "NGAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([NGAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NOUSguide Inc. 2 | 3 | # NGVaryingGridView 4 | 5 | A GridView which allows to set individual Rects for the Cells. So you can define Cells with different Sizes, used e.g. in Timetables, EPGs, etc. 6 | 7 | Sticky Views are also supported on top of the GridView and on the left side. 8 | 9 | NGVaryingGridView 10 | 11 | 12 | 13 | ## Usage 14 | 15 | ``` objective-c 16 | self.gridView = [[NGVaryingGridView alloc] initWithFrame:self.view.bounds]; 17 | self.gridView.gridViewDelegate = self; 18 | [self.view addSubview:self.gridView]; 19 | 20 | [self.gridView reloadData]; 21 | ``` 22 | 23 | The following Delegate-Methods are required: 24 | 25 | ``` objective-c 26 | // You should return an Array which contains CGRects for every Cell you want to display inside the GridView 27 | - (NSArray *)rectsForCellsInGridView:(NGVaryingGridView *)gridView { 28 | NSMutableArray *rectsArray = [NSMutableArray array]; 29 | [array addObject:[NSValue valueWithCGRect:CGrectMake(...)]] 30 | 31 | // ... 32 | 33 | return rectsArray; 34 | } 35 | 36 | // return an UIView representing your Cell 37 | - (UIView *)gridView:(NGVaryingGridView *)gridView viewForCellWithRect:(CGRect)rect index:(NSUInteger)index { 38 | YourUIViewSubclass *gridCell = (YourUIViewSubclass *)[gridView dequeueReusableCell] ? : [[YourUIViewSubclass alloc] initWithFrame:rect]; 39 | gridCell.frame = rect; 40 | 41 | // setup gridCell 42 | 43 | return gridCell 44 | } 45 | ``` 46 | 47 | Just have a look inside the provided Demo-Application. 48 | 49 | ## Credits 50 | 51 | NGVaryingGridView was created by [Philip Messlehner](https://github.com/messi/) 52 | 53 | ## License 54 | 55 | NGPageControl is available under the MIT license. See the LICENSE file for more info. 56 | For usage without attribution contact [NOUSguide](mailto:info@nousguide.com). --------------------------------------------------------------------------------