├── .gitignore ├── CPPickerView.podspec ├── CPPickerView ├── CPPickerView.h ├── CPPickerView.m ├── CPPickerViewCell.h └── CPPickerViewCell.m ├── CPPickerViewDemo.xcodeproj └── project.pbxproj ├── CPPickerViewDemo ├── AppDelegate.h ├── AppDelegate.m ├── CPPickerViewDemo-Info.plist ├── CPPickerViewDemo-Prefix.pch ├── TableViewController.h ├── TableViewController.m ├── TableViewController.xib ├── ViewController.h ├── ViewController.m ├── en.lproj │ ├── InfoPlist.strings │ └── ViewController.xib └── main.m ├── Default-568h@2x.png ├── Image Resources ├── Graphics.psd └── StretchableGlass.psd ├── LICENSE ├── README.md └── Resources ├── shadowOverlay@2x.png ├── stretchableGlass@2x.png └── wheelBackground@2x.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X Finder and whatnot 2 | .DS_Store 3 | 4 | 5 | # Sparkle distribution Private Key (Don't check me in!) 6 | dsa_priv.pem 7 | 8 | 9 | # XCode (and ancestors) per-user config (very noisy, and not relevant) 10 | xcuserdata 11 | *.mode1 12 | *.mode1v3 13 | *.mode2v3 14 | *.perspective 15 | *.perspectivev3 16 | *.pbxuser 17 | *.xcuserdata 18 | *.xcuserstate 19 | *.xcworkspace 20 | 21 | 22 | # Generated files 23 | VersionX-revision.h 24 | 25 | 26 | # build products 27 | build/ 28 | 29 | 30 | # Other source repository archive directories (protects when importing) 31 | .hg 32 | .svn 33 | CVS 34 | 35 | 36 | # automatic backup files 37 | *~.nib 38 | *.swp 39 | *~ 40 | *(Autosaved).rtfd/ 41 | Backup[ ]of[ ]*.pages/ 42 | Backup[ ]of[ ]*.key/ 43 | Backup[ ]of[ ]*.numbers/ 44 | [#]*[#] 45 | -------------------------------------------------------------------------------- /CPPickerView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "CPPickerView" 3 | s.version = "1.2.0" 4 | s.summary = "A custom, configurable, horizontal version of UIPickerView built to live in a UITableViewCell." 5 | s.homepage = "https://github.com/cbpowell/CPPickerView" 6 | s.license = { :type => 'MIT', :file => 'LICENSE' } 7 | s.author = { "Charles Powell" => "cbpowell@gmail.com" } 8 | s.source = { :git => "https://github.com/cbpowell/CPPickerView.git", :tag => s.version.to_s } 9 | s.platform = :ios, '5.0' 10 | s.source_files = 'CPPickerView/*.{h,m}' 11 | s.resources = 'Resources/*.png' 12 | s.requires_arc = true 13 | end 14 | -------------------------------------------------------------------------------- /CPPickerView/CPPickerView.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Charles Powell 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /** 27 | * Based heavily on AFPickerView by Fraerman Arkady 28 | * https://github.com/arkichek/AFPickerView 29 | */ 30 | 31 | // 32 | // CPPickerView.h 33 | // 34 | 35 | #import 36 | #import 37 | 38 | 39 | @protocol CPPickerViewDataSource; 40 | @protocol CPPickerViewDelegate; 41 | 42 | @interface CPPickerView : UIView 43 | 44 | // Datasource and delegate 45 | @property (nonatomic, unsafe_unretained) IBOutlet id dataSource; 46 | @property (nonatomic, unsafe_unretained) IBOutlet id delegate; 47 | // Current status 48 | @property (nonatomic) NSUInteger selectedItem; 49 | @property (nonatomic) BOOL enabled; 50 | // Configuration 51 | @property (nonatomic, strong) UIFont *itemFont; 52 | @property (nonatomic, strong) UIColor *itemColor; 53 | @property (nonatomic) BOOL showGlass; 54 | @property (nonatomic) UIEdgeInsets peekInset; 55 | @property (nonatomic) BOOL allowSlowDeceleration; 56 | // Images 57 | @property (nonatomic, strong) UIImage *backgroundImage; 58 | @property (nonatomic, strong) UIImage *glassImage; 59 | @property (nonatomic, strong) UIImage *shadowImage; 60 | 61 | // Control methods 62 | - (void)reloadData; 63 | - (void)setSelectedItem:(NSUInteger)selectedItem animated:(BOOL)animated; 64 | - (void)selectItemAtIndex:(NSInteger)index animated:(BOOL)animated __attribute((deprecated("Use setSelectedItem:animated: method instead"))); 65 | 66 | // View queue 67 | - (UIView *)dequeueRecycledView; 68 | - (BOOL)isDisplayingViewForIndex:(NSUInteger)index; 69 | 70 | @end 71 | 72 | 73 | 74 | @protocol CPPickerViewDataSource 75 | 76 | - (NSInteger)numberOfItemsInPickerView:(CPPickerView *)pickerView; 77 | - (NSString *)pickerView:(CPPickerView *)pickerView titleForItem:(NSInteger)item; 78 | 79 | @end 80 | 81 | 82 | 83 | @protocol CPPickerViewDelegate 84 | 85 | - (void)pickerView:(CPPickerView *)pickerView didSelectItem:(NSInteger)item; 86 | 87 | @optional 88 | 89 | - (void)pickerViewWillBeginChangingItem:(CPPickerView *)pickerView; 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /CPPickerView/CPPickerView.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Charles Powell 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /** 27 | * Based heavily on AFPickerView by Fraerman Arkady 28 | * https://github.com/arkichek/AFPickerView 29 | */ 30 | 31 | // 32 | // CPPickerView.m 33 | // 34 | 35 | #import "CPPickerView.h" 36 | 37 | #define kCPPickerDecelerationThreshold 2.9f 38 | 39 | @interface CPPickerView () 40 | 41 | // Views 42 | @property (nonatomic, strong) UIScrollView *contentView; 43 | 44 | // recycling 45 | @property (nonatomic, strong) NSMutableSet *recycledViews; 46 | @property (nonatomic, strong) NSMutableSet *visibleViews; 47 | 48 | @property (nonatomic) NSUInteger itemCount; 49 | 50 | - (void)setup; 51 | 52 | - (void)determineCurrentItem; 53 | - (void)tileViews; 54 | - (void)configureView:(UIView *)view atIndex:(NSUInteger)index; 55 | 56 | @end 57 | 58 | @implementation CPPickerView 59 | 60 | #pragma mark - Initialization 61 | 62 | 63 | - (id)initWithFrame:(CGRect)frame 64 | { 65 | self = [super initWithFrame:frame]; 66 | if (self) 67 | { 68 | [self commonInit]; 69 | } 70 | return self; 71 | } 72 | 73 | 74 | -(id)initWithCoder:(NSCoder *)aDecoder 75 | { 76 | if ((self = [super initWithCoder:aDecoder])) 77 | { 78 | [self commonInit]; 79 | } 80 | return self; 81 | } 82 | 83 | -(void)commonInit 84 | { 85 | // setup 86 | [self setup]; 87 | 88 | // content 89 | self.contentView = [[UIScrollView alloc] initWithFrame:UIEdgeInsetsInsetRect(self.bounds, self.peekInset)]; 90 | self.contentView.clipsToBounds = NO; 91 | self.contentView.showsHorizontalScrollIndicator = NO; 92 | self.contentView.showsVerticalScrollIndicator = NO; 93 | self.contentView.pagingEnabled = YES; 94 | self.contentView.scrollsToTop = NO; 95 | self.contentView.delegate = self; 96 | [self addSubview:self.contentView]; 97 | 98 | // Images 99 | if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0) { 100 | self.backgroundImage = [[UIImage imageNamed:@"wheelBackground"] resizableImageWithCapInsets:UIEdgeInsetsMake(5, 0, 5, 0)]; 101 | self.glassImage = [[UIImage imageNamed:@"stretchableGlass"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 1, 0, 1)]; 102 | } else { 103 | self.backgroundImage = [[UIImage imageNamed:@"wheelBackground"] stretchableImageWithLeftCapWidth:0 topCapHeight:5]; 104 | self.glassImage = [[UIImage imageNamed:@"stretchableGlass"] stretchableImageWithLeftCapWidth:1 topCapHeight:0]; 105 | } 106 | self.shadowImage = [UIImage imageNamed:@"shadowOverlay"]; 107 | 108 | // Rounded borders 109 | self.layer.cornerRadius = 3.0f; 110 | self.clipsToBounds = YES; 111 | self.layer.borderColor = [UIColor colorWithWhite:0.15 alpha:1.0].CGColor; 112 | self.layer.borderWidth = 0.5f; 113 | } 114 | 115 | 116 | - (void)setup 117 | { 118 | _itemFont = [UIFont boldSystemFontOfSize:24.0]; 119 | _itemColor = [UIColor blackColor]; 120 | _showGlass = NO; 121 | _allowSlowDeceleration = NO; 122 | _peekInset = UIEdgeInsetsMake(0, 0, 0, 0); 123 | _selectedItem = 0; 124 | _itemCount = 0; 125 | _visibleViews = [[NSMutableSet alloc] init]; 126 | _recycledViews = [[NSMutableSet alloc] init]; 127 | } 128 | 129 | #pragma mark - View Handling 130 | 131 | - (void)layoutSubviews 132 | { 133 | [super layoutSubviews]; 134 | 135 | self.contentView.frame = UIEdgeInsetsInsetRect(self.bounds, self.peekInset); 136 | } 137 | 138 | - (void)drawRect:(CGRect)rect { 139 | 140 | // Draw background 141 | if (self.backgroundImage) { 142 | [self.backgroundImage drawInRect:self.bounds]; 143 | } 144 | 145 | // Draw super/UIScrollView 146 | [super drawRect:rect]; 147 | 148 | // Draw shadow 149 | if (self.shadowImage) { 150 | [self.shadowImage drawInRect:self.bounds]; 151 | } 152 | 153 | // Draw glass 154 | if (self.showGlass && self.glassImage) { 155 | [self.glassImage drawInRect:CGRectMake(self.frame.size.width / 2 - 30, 0.0, 60, self.frame.size.height)]; 156 | } 157 | } 158 | 159 | #pragma mark - Custom Getters/Setters 160 | 161 | - (void)setSelectedItem:(NSUInteger)selectedItem 162 | { 163 | [self setSelectedItem:selectedItem animated:NO]; 164 | } 165 | 166 | - (void)setSelectedItem:(NSUInteger)selectedItem animated:(BOOL)animated 167 | { 168 | if (selectedItem >= self.itemCount || selectedItem == _selectedItem) { 169 | return; 170 | } 171 | 172 | _selectedItem = selectedItem; 173 | [self scrollToIndex:_selectedItem animated:animated]; 174 | if ([self.delegate respondsToSelector:@selector(pickerView:didSelectItem:)]) { 175 | [self.delegate pickerView:self didSelectItem:_selectedItem]; 176 | } 177 | } 178 | 179 | - (void)setItemFont:(UIFont *)itemFont 180 | { 181 | _itemFont = itemFont; 182 | 183 | for (UILabel *aLabel in self.visibleViews) 184 | { 185 | aLabel.font = _itemFont; 186 | } 187 | 188 | for (UILabel *aLabel in self.recycledViews) 189 | { 190 | aLabel.font = _itemFont; 191 | } 192 | } 193 | 194 | - (void)setItemColor:(UIColor *)itemColor 195 | { 196 | _itemColor = itemColor; 197 | 198 | for (UILabel *aLabel in self.visibleViews) 199 | { 200 | aLabel.textColor = _itemColor; 201 | } 202 | 203 | for (UILabel *aLabel in self.recycledViews) 204 | { 205 | aLabel.textColor = _itemColor; 206 | } 207 | } 208 | 209 | - (void)setShowGlass:(BOOL)doShowGlass { 210 | if (_showGlass != doShowGlass) { 211 | _showGlass = doShowGlass; 212 | [self setNeedsDisplay]; 213 | } 214 | } 215 | 216 | - (void)setPeekInset:(UIEdgeInsets)aPeekInset { 217 | if (!UIEdgeInsetsEqualToEdgeInsets(_peekInset, aPeekInset)) { 218 | _peekInset = aPeekInset; 219 | self.contentView.frame = UIEdgeInsetsInsetRect(self.bounds, _peekInset); 220 | [self reloadData]; 221 | [self.contentView setNeedsDisplay]; 222 | } 223 | } 224 | 225 | - (void)setBackgroundImage:(UIImage *)backgroundImage 226 | { 227 | if ([backgroundImage isEqual:_backgroundImage]) { 228 | return; 229 | } 230 | 231 | _backgroundImage = backgroundImage; 232 | [self setNeedsDisplay]; 233 | } 234 | 235 | - (void)setGlassImage:(UIImage *)glassImage 236 | { 237 | if ([glassImage isEqual:_glassImage]) { 238 | return; 239 | } 240 | 241 | _glassImage = glassImage; 242 | [self setNeedsDisplay]; 243 | } 244 | 245 | - (void)setShadowImage:(UIImage *)shadowImage 246 | { 247 | if ([shadowImage isEqual:_shadowImage]) { 248 | return; 249 | } 250 | 251 | _shadowImage = shadowImage; 252 | [self setNeedsDisplay]; 253 | } 254 | 255 | #pragma mark - Touch Handling 256 | 257 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 258 | 259 | if ([self pointInside:point withEvent:event]) { 260 | return self.contentView; 261 | } 262 | 263 | return nil; 264 | } 265 | 266 | 267 | #pragma mark - Data handling and interaction 268 | 269 | - (void)reloadData 270 | { 271 | // empty views 272 | _selectedItem = 0; 273 | _itemCount = 0; 274 | 275 | for (UIView *aView in self.visibleViews) 276 | [aView removeFromSuperview]; 277 | 278 | for (UIView *aView in self.recycledViews) 279 | [aView removeFromSuperview]; 280 | 281 | self.visibleViews = [[NSMutableSet alloc] init]; 282 | self.recycledViews = [[NSMutableSet alloc] init]; 283 | 284 | if ([self.dataSource respondsToSelector:@selector(numberOfItemsInPickerView:)]) { 285 | self.itemCount = [self.dataSource numberOfItemsInPickerView:self]; 286 | } else { 287 | self.itemCount = 0; 288 | } 289 | 290 | [self scrollToIndex:0 animated:NO]; 291 | self.contentView.frame = UIEdgeInsetsInsetRect(self.bounds, self.peekInset); 292 | self.contentView.contentSize = CGSizeMake(self.contentView.frame.size.width * self.itemCount, self.contentView.frame.size.height); 293 | [self tileViews]; 294 | } 295 | 296 | - (void)determineCurrentItem 297 | { 298 | CGFloat delta = self.contentView.contentOffset.x; 299 | NSUInteger position = round(delta / self.contentView.frame.size.width); 300 | _selectedItem = position; 301 | if ([self.delegate respondsToSelector:@selector(pickerView:didSelectItem:)]) { 302 | [self.delegate pickerView:self didSelectItem:_selectedItem]; 303 | } 304 | } 305 | 306 | - (void)selectItemAtIndex:(NSInteger)index animated:(BOOL)animated { 307 | [self setSelectedItem:index animated:animated]; 308 | } 309 | 310 | - (void)scrollToIndex:(NSInteger)index animated:(BOOL)animated { 311 | [self.contentView setContentOffset:CGPointMake(self.contentView.frame.size.width * index, 0.0) animated:animated]; 312 | } 313 | 314 | 315 | - (BOOL)enabled { 316 | return self.contentView.scrollEnabled; 317 | } 318 | 319 | - (void)setEnabled:(BOOL)enabled { 320 | self.contentView.scrollEnabled = enabled; 321 | } 322 | 323 | 324 | #pragma mark - recycle queue 325 | 326 | - (UIView *)dequeueRecycledView 327 | { 328 | UIView *aView = [self.recycledViews anyObject]; 329 | 330 | if (aView) 331 | [self.recycledViews removeObject:aView]; 332 | return aView; 333 | } 334 | 335 | - (BOOL)isDisplayingViewForIndex:(NSUInteger)index 336 | { 337 | BOOL foundPage = NO; 338 | for (UIView *aView in self.visibleViews) 339 | { 340 | int viewIndex = aView.frame.origin.x / self.contentView.frame.size.width; 341 | if (viewIndex == index) 342 | { 343 | foundPage = YES; 344 | break; 345 | } 346 | } 347 | return foundPage; 348 | } 349 | 350 | - (void)tileViews 351 | { 352 | // Calculate which pages are visible 353 | CGRect visibleBounds = self.contentView.bounds; 354 | int currentViewIndex = floorf(self.contentView.contentOffset.x / self.contentView.frame.size.width); 355 | int firstNeededViewIndex = currentViewIndex - 2; 356 | int lastNeededViewIndex = currentViewIndex + 2; 357 | firstNeededViewIndex = MAX(firstNeededViewIndex, 0); 358 | lastNeededViewIndex = MIN(lastNeededViewIndex, self.itemCount - 1); 359 | 360 | // Recycle no-longer-visible pages 361 | for (UIView *aView in self.visibleViews) 362 | { 363 | int viewIndex = aView.frame.origin.x / visibleBounds.size.width - 2; 364 | if (viewIndex < firstNeededViewIndex || viewIndex > lastNeededViewIndex) 365 | { 366 | [self.recycledViews addObject:aView]; 367 | [aView removeFromSuperview]; 368 | } 369 | } 370 | 371 | [self.visibleViews minusSet:self.recycledViews]; 372 | 373 | // add missing pages 374 | for (int index = firstNeededViewIndex; index <= lastNeededViewIndex; index++) 375 | { 376 | if (![self isDisplayingViewForIndex:index]) 377 | { 378 | UILabel *label = (UILabel *)[self dequeueRecycledView]; 379 | 380 | if (label == nil) 381 | { 382 | label = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, self.contentView.frame.size.width, self.contentView.frame.size.height)]; 383 | label.backgroundColor = [UIColor clearColor]; 384 | label.font = self.itemFont; 385 | label.textColor = self.itemColor; 386 | label.textAlignment = NSTextAlignmentCenter; 387 | } 388 | 389 | [self configureView:label atIndex:index]; 390 | [self.contentView addSubview:label]; 391 | [self.visibleViews addObject:label]; 392 | } 393 | } 394 | } 395 | 396 | - (void)configureView:(UIView *)view atIndex:(NSUInteger)index 397 | { 398 | UILabel *label = (UILabel *)view; 399 | 400 | if ([self.dataSource respondsToSelector:@selector(pickerView:titleForItem:)]) { 401 | label.text = [self.dataSource pickerView:self titleForItem:index]; 402 | } 403 | 404 | CGRect frame = label.frame; 405 | frame.origin.x = self.contentView.frame.size.width * index; 406 | label.frame = frame; 407 | } 408 | 409 | 410 | #pragma mark - UIScrollViewDelegate 411 | 412 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 413 | { 414 | [self tileViews]; 415 | } 416 | 417 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 418 | { 419 | [self determineCurrentItem]; 420 | 421 | if (!self.contentView.pagingEnabled) { 422 | [self scrollToIndex:self.selectedItem animated:YES]; 423 | } 424 | } 425 | 426 | - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView 427 | { 428 | self.contentView.pagingEnabled = YES; 429 | } 430 | 431 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 432 | { 433 | if (velocity.x > kCPPickerDecelerationThreshold && self.allowSlowDeceleration) { 434 | // Disable paging momentarily to allow slow decel 435 | self.contentView.pagingEnabled = NO; 436 | } 437 | } 438 | 439 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 440 | { 441 | if ([self.delegate respondsToSelector:@selector(pickerViewWillBeginChangingItem:)]) { 442 | [self.delegate pickerViewWillBeginChangingItem:self]; 443 | } 444 | } 445 | 446 | 447 | @end 448 | -------------------------------------------------------------------------------- /CPPickerView/CPPickerViewCell.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 Charles Powell 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | // 27 | // CPPickerViewCell.h 28 | // PickerView 29 | // 30 | 31 | 32 | #import 33 | #import "CPPickerView.h" 34 | 35 | @protocol CPPickerViewCellDataSource; 36 | @protocol CPPickerViewCellDelegate; 37 | 38 | @interface CPPickerViewCell : UITableViewCell 39 | 40 | @property (nonatomic, unsafe_unretained) id dataSource; 41 | @property (nonatomic, unsafe_unretained) id delegate; 42 | 43 | @property (nonatomic, readonly) CPPickerView *pickerView; 44 | @property (nonatomic, readonly) NSUInteger selectedItem; 45 | @property (nonatomic, copy) NSIndexPath *currentIndexPath; 46 | 47 | @property (nonatomic, strong) UIFont *itemFont; 48 | @property (nonatomic, strong) UIColor *itemColor; 49 | @property (nonatomic) BOOL showGlass; 50 | @property (nonatomic) UIEdgeInsets peekInset; 51 | @property (nonatomic) BOOL allowSlowDeceleration; 52 | 53 | // Handling 54 | - (void)reloadData; 55 | - (void)setSelectedItem:(NSUInteger)selectedItem; 56 | - (void)setSelectedItem:(NSUInteger)selectedItem animated:(BOOL)animated; 57 | 58 | - (void)selectItemAtIndex:(NSInteger)index animated:(BOOL)animated __attribute((deprecated("Use setSelectedItem:animated: method instead"))); 59 | 60 | @end 61 | 62 | 63 | 64 | @protocol CPPickerViewCellDataSource 65 | 66 | - (NSInteger)numberOfItemsInPickerViewAtIndexPath:(NSIndexPath *)pickerPath; 67 | - (NSString *)pickerViewAtIndexPath:(NSIndexPath *)pickerPath titleForItem:(NSInteger)item; 68 | 69 | @end 70 | 71 | @protocol CPPickerViewCellDelegate 72 | 73 | - (void)pickerViewAtIndexPath:(NSIndexPath *)pickerPath didSelectItem:(NSInteger)item; 74 | 75 | @optional 76 | 77 | - (void)pickerViewAtIndexPathWillBeginChangingItem:(NSIndexPath *)pickerPath; 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /CPPickerView/CPPickerViewCell.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2012 Charles Powell 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | // 27 | // CPPickerViewCell.m 28 | // PickerView 29 | // 30 | 31 | 32 | #import "CPPickerViewCell.h" 33 | 34 | @interface CPPickerViewCell () 35 | 36 | @property (nonatomic, readwrite, unsafe_unretained) CPPickerView *pickerView; 37 | 38 | @end 39 | 40 | 41 | 42 | @implementation CPPickerViewCell 43 | 44 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 45 | { 46 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 47 | if (self) { 48 | CPPickerView *newPickerView = [[CPPickerView alloc] initWithFrame:CGRectMake(192, 8, 112, 30)]; 49 | [self addSubview:newPickerView]; 50 | self.pickerView = newPickerView; 51 | self.pickerView.delegate = self; 52 | self.pickerView.dataSource = self; 53 | self.pickerView.itemFont = [UIFont boldSystemFontOfSize:14]; 54 | self.pickerView.itemColor = [UIColor blackColor]; 55 | } 56 | return self; 57 | } 58 | 59 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated 60 | { 61 | [super setSelected:selected animated:animated]; 62 | 63 | } 64 | 65 | - (NSIndexPath *)currentIndexPath { 66 | if (_currentIndexPath == nil) { 67 | _currentIndexPath = [(UITableView *)self.superview indexPathForCell:self]; 68 | } 69 | return _currentIndexPath; 70 | } 71 | 72 | - (void)prepareForReuse { 73 | [super prepareForReuse]; 74 | 75 | self.currentIndexPath = nil; 76 | } 77 | 78 | #pragma mark External 79 | 80 | - (void)reloadData { 81 | [self.pickerView reloadData]; 82 | } 83 | 84 | - (void)setSelectedItem:(NSUInteger)selectedItem { 85 | [self setSelectedItem:selectedItem animated:YES]; 86 | } 87 | 88 | - (void)setSelectedItem:(NSUInteger)selectedItem animated:(BOOL)animated { 89 | [self.pickerView setSelectedItem:selectedItem animated:animated]; 90 | } 91 | 92 | - (void)selectItemAtIndex:(NSInteger)index animated:(BOOL)animated { 93 | [self.pickerView setSelectedItem:index animated:animated]; 94 | } 95 | 96 | #pragma mark CPPickerView Delegate 97 | 98 | - (void)pickerView:(CPPickerView *)pickerView didSelectItem:(NSInteger)item { 99 | if ([self.delegate respondsToSelector:@selector(pickerViewAtIndexPath:didSelectItem:)]) { 100 | [self.delegate pickerViewAtIndexPath:self.currentIndexPath didSelectItem:item]; 101 | } 102 | } 103 | 104 | - (void)pickerViewWillBeginChangingItem:(CPPickerView *)pickerView { 105 | if ([self.delegate respondsToSelector:@selector(pickerViewAtIndexPathWillBeginChangingItem:)]) { 106 | [self.delegate pickerViewAtIndexPathWillBeginChangingItem:self.currentIndexPath]; 107 | } 108 | } 109 | 110 | #pragma mark CPPickerView Datasource 111 | 112 | - (NSInteger)numberOfItemsInPickerView:(CPPickerView *)pickerView { 113 | NSInteger numberOfItems = 0; 114 | if ([self.dataSource respondsToSelector:@selector(numberOfItemsInPickerViewAtIndexPath:)]) { 115 | numberOfItems = [self.dataSource numberOfItemsInPickerViewAtIndexPath:self.currentIndexPath]; 116 | } 117 | 118 | return numberOfItems; 119 | } 120 | 121 | - (NSString *)pickerView:(CPPickerView *)pickerView titleForItem:(NSInteger)item { 122 | NSString *title = nil; 123 | if ([self.dataSource respondsToSelector:@selector(pickerViewAtIndexPath:titleForItem:)]) { 124 | title = [self.dataSource pickerViewAtIndexPath:self.currentIndexPath titleForItem:item]; 125 | } 126 | 127 | return title; 128 | } 129 | 130 | #pragma mark Custom getters/setters 131 | 132 | - (NSUInteger)selectedItem { 133 | return [self.pickerView selectedItem]; 134 | } 135 | 136 | - (void)setShowGlass:(BOOL)doShowGlass { 137 | self.pickerView.showGlass = doShowGlass; 138 | } 139 | 140 | - (BOOL)showGlass { 141 | return self.pickerView.showGlass; 142 | } 143 | 144 | - (void)setPeekInset:(UIEdgeInsets)aPeekInset { 145 | self.pickerView.peekInset = aPeekInset; 146 | } 147 | 148 | - (UIEdgeInsets)peekInset { 149 | return self.pickerView.peekInset; 150 | } 151 | 152 | - (void)setItemColor:(UIColor *)itemColor { 153 | self.pickerView.itemColor = itemColor; 154 | } 155 | 156 | - (UIColor *)itemColor { 157 | return self.pickerView.itemColor; 158 | } 159 | 160 | - (void)setItemFont:(UIFont *)itemFont { 161 | self.pickerView.itemFont = itemFont; 162 | } 163 | 164 | - (UIFont *)itemFont { 165 | return self.pickerView.itemFont; 166 | } 167 | 168 | - (void)setAllowSlowDeceleration:(BOOL)allowSlowDeceleration { 169 | self.pickerView.allowSlowDeceleration = allowSlowDeceleration; 170 | } 171 | 172 | - (BOOL)allowSlowDeceleration { 173 | return self.pickerView.allowSlowDeceleration; 174 | } 175 | 176 | @end 177 | -------------------------------------------------------------------------------- /CPPickerViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0A3DA65B147E3D9700143ADF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A3DA65A147E3D9700143ADF /* UIKit.framework */; }; 11 | 0A3DA65D147E3D9700143ADF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A3DA65C147E3D9700143ADF /* Foundation.framework */; }; 12 | 0A3DA65F147E3D9700143ADF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A3DA65E147E3D9700143ADF /* CoreGraphics.framework */; }; 13 | 0A3DA66B147E3D9700143ADF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A3DA66A147E3D9700143ADF /* AppDelegate.m */; }; 14 | 0A3DA66E147E3D9700143ADF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A3DA66D147E3D9700143ADF /* ViewController.m */; }; 15 | 0A3DA68D147E53B700143ADF /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A3DA68C147E53B700143ADF /* QuartzCore.framework */; }; 16 | EA4BF4731881BA71002CB644 /* shadowOverlay@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EA4BF4701881BA71002CB644 /* shadowOverlay@2x.png */; }; 17 | EA4BF4741881BA71002CB644 /* stretchableGlass@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EA4BF4711881BA71002CB644 /* stretchableGlass@2x.png */; }; 18 | EA4BF4751881BA71002CB644 /* wheelBackground@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EA4BF4721881BA71002CB644 /* wheelBackground@2x.png */; }; 19 | EA4BF47818820BB0002CB644 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = EA4BF47718820BB0002CB644 /* Default-568h@2x.png */; }; 20 | EA5013431516D23C00917CFA /* CPPickerViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = EA5013411516D23C00917CFA /* CPPickerViewCell.m */; }; 21 | EA58F3411881B91E00204A7E /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0A3DA66F147E3D9700143ADF /* ViewController.xib */; }; 22 | EA58F3421881B91E00204A7E /* TableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = EA5C7F8F1516717B0062E922 /* TableViewController.xib */; }; 23 | EA58F3431881B91E00204A7E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0A3DA663147E3D9700143ADF /* InfoPlist.strings */; }; 24 | EA5C7F901516717B0062E922 /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EA5C7F8E1516717B0062E922 /* TableViewController.m */; }; 25 | EA6B58B31793166400455D55 /* CPPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = EA6B58B217930C8500455D55 /* CPPickerView.m */; }; 26 | EA6B58B41793168E00455D55 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A3DA666147E3D9700143ADF /* main.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 0A3DA656147E3D9700143ADF /* CPPickerViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CPPickerViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 0A3DA65A147E3D9700143ADF /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 32 | 0A3DA65C147E3D9700143ADF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 33 | 0A3DA65E147E3D9700143ADF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 34 | 0A3DA662147E3D9700143ADF /* CPPickerViewDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "CPPickerViewDemo-Info.plist"; path = "../CPPickerViewDemo/CPPickerViewDemo-Info.plist"; sourceTree = ""; }; 35 | 0A3DA664147E3D9700143ADF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 36 | 0A3DA666147E3D9700143ADF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ../CPPickerViewDemo/main.m; sourceTree = ""; }; 37 | 0A3DA668147E3D9700143ADF /* CPPickerViewDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "CPPickerViewDemo-Prefix.pch"; path = "../CPPickerViewDemo/CPPickerViewDemo-Prefix.pch"; sourceTree = ""; }; 38 | 0A3DA669147E3D9700143ADF /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ../CPPickerViewDemo/AppDelegate.h; sourceTree = ""; }; 39 | 0A3DA66A147E3D9700143ADF /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ../CPPickerViewDemo/AppDelegate.m; sourceTree = ""; }; 40 | 0A3DA66C147E3D9700143ADF /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ViewController.h; path = ../CPPickerViewDemo/ViewController.h; sourceTree = ""; }; 41 | 0A3DA66D147E3D9700143ADF /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ViewController.m; path = ../CPPickerViewDemo/ViewController.m; sourceTree = ""; }; 42 | 0A3DA670147E3D9700143ADF /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; 43 | 0A3DA68C147E53B700143ADF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 44 | EA4BF4701881BA71002CB644 /* shadowOverlay@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "shadowOverlay@2x.png"; path = "Resources/shadowOverlay@2x.png"; sourceTree = SOURCE_ROOT; }; 45 | EA4BF4711881BA71002CB644 /* stretchableGlass@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "stretchableGlass@2x.png"; path = "Resources/stretchableGlass@2x.png"; sourceTree = SOURCE_ROOT; }; 46 | EA4BF4721881BA71002CB644 /* wheelBackground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "wheelBackground@2x.png"; path = "Resources/wheelBackground@2x.png"; sourceTree = SOURCE_ROOT; }; 47 | EA4BF47718820BB0002CB644 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 48 | EA50133E1516D23C00917CFA /* CPPickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPPickerView.h; path = CPPickerView/CPPickerView.h; sourceTree = SOURCE_ROOT; }; 49 | EA5013401516D23C00917CFA /* CPPickerViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPPickerViewCell.h; path = CPPickerView/CPPickerViewCell.h; sourceTree = SOURCE_ROOT; }; 50 | EA5013411516D23C00917CFA /* CPPickerViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CPPickerViewCell.m; path = CPPickerView/CPPickerViewCell.m; sourceTree = SOURCE_ROOT; }; 51 | EA5C7F8D1516717B0062E922 /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TableViewController.h; path = ../CPPickerViewDemo/TableViewController.h; sourceTree = ""; }; 52 | EA5C7F8E1516717B0062E922 /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TableViewController.m; path = ../CPPickerViewDemo/TableViewController.m; sourceTree = ""; }; 53 | EA5C7F8F1516717B0062E922 /* TableViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TableViewController.xib; path = ../CPPickerViewDemo/TableViewController.xib; sourceTree = ""; }; 54 | EA6B58B217930C8500455D55 /* CPPickerView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CPPickerView.m; path = CPPickerView/CPPickerView.m; sourceTree = SOURCE_ROOT; }; 55 | /* End PBXFileReference section */ 56 | 57 | /* Begin PBXFrameworksBuildPhase section */ 58 | 0A3DA653147E3D9700143ADF /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | 0A3DA65B147E3D9700143ADF /* UIKit.framework in Frameworks */, 63 | 0A3DA65D147E3D9700143ADF /* Foundation.framework in Frameworks */, 64 | 0A3DA65F147E3D9700143ADF /* CoreGraphics.framework in Frameworks */, 65 | 0A3DA68D147E53B700143ADF /* QuartzCore.framework in Frameworks */, 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | /* End PBXFrameworksBuildPhase section */ 70 | 71 | /* Begin PBXGroup section */ 72 | 0A3DA64B147E3D9700143ADF = { 73 | isa = PBXGroup; 74 | children = ( 75 | EA4BF47718820BB0002CB644 /* Default-568h@2x.png */, 76 | 0A3DA677147E3DAB00143ADF /* CPPickerView */, 77 | 0A3DA660147E3D9700143ADF /* CPPickerViewDemo */, 78 | 0A3DA659147E3D9700143ADF /* Frameworks */, 79 | 0A3DA657147E3D9700143ADF /* Products */, 80 | ); 81 | sourceTree = ""; 82 | }; 83 | 0A3DA657147E3D9700143ADF /* Products */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 0A3DA656147E3D9700143ADF /* CPPickerViewDemo.app */, 87 | ); 88 | name = Products; 89 | sourceTree = ""; 90 | }; 91 | 0A3DA659147E3D9700143ADF /* Frameworks */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 0A3DA68C147E53B700143ADF /* QuartzCore.framework */, 95 | 0A3DA65A147E3D9700143ADF /* UIKit.framework */, 96 | 0A3DA65C147E3D9700143ADF /* Foundation.framework */, 97 | 0A3DA65E147E3D9700143ADF /* CoreGraphics.framework */, 98 | ); 99 | name = Frameworks; 100 | sourceTree = ""; 101 | }; 102 | 0A3DA660147E3D9700143ADF /* CPPickerViewDemo */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 0A3DA669147E3D9700143ADF /* AppDelegate.h */, 106 | 0A3DA66A147E3D9700143ADF /* AppDelegate.m */, 107 | 0A3DA66C147E3D9700143ADF /* ViewController.h */, 108 | 0A3DA66D147E3D9700143ADF /* ViewController.m */, 109 | 0A3DA66F147E3D9700143ADF /* ViewController.xib */, 110 | EA5C7F8D1516717B0062E922 /* TableViewController.h */, 111 | EA5C7F8E1516717B0062E922 /* TableViewController.m */, 112 | EA5C7F8F1516717B0062E922 /* TableViewController.xib */, 113 | 0A3DA661147E3D9700143ADF /* Supporting Files */, 114 | ); 115 | path = CPPickerViewDemo; 116 | sourceTree = ""; 117 | }; 118 | 0A3DA661147E3D9700143ADF /* Supporting Files */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 0A3DA662147E3D9700143ADF /* CPPickerViewDemo-Info.plist */, 122 | 0A3DA663147E3D9700143ADF /* InfoPlist.strings */, 123 | 0A3DA666147E3D9700143ADF /* main.m */, 124 | 0A3DA668147E3D9700143ADF /* CPPickerViewDemo-Prefix.pch */, 125 | ); 126 | name = "Supporting Files"; 127 | sourceTree = ""; 128 | }; 129 | 0A3DA677147E3DAB00143ADF /* CPPickerView */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | EA50133E1516D23C00917CFA /* CPPickerView.h */, 133 | EA6B58B217930C8500455D55 /* CPPickerView.m */, 134 | EA5013401516D23C00917CFA /* CPPickerViewCell.h */, 135 | EA5013411516D23C00917CFA /* CPPickerViewCell.m */, 136 | EA4BF4761881BA78002CB644 /* Resources */, 137 | ); 138 | name = CPPickerView; 139 | path = PickerView; 140 | sourceTree = ""; 141 | }; 142 | EA4BF4761881BA78002CB644 /* Resources */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | EA4BF4701881BA71002CB644 /* shadowOverlay@2x.png */, 146 | EA4BF4711881BA71002CB644 /* stretchableGlass@2x.png */, 147 | EA4BF4721881BA71002CB644 /* wheelBackground@2x.png */, 148 | ); 149 | name = Resources; 150 | sourceTree = ""; 151 | }; 152 | /* End PBXGroup section */ 153 | 154 | /* Begin PBXNativeTarget section */ 155 | 0A3DA655147E3D9700143ADF /* CPPickerViewDemo */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = 0A3DA674147E3D9700143ADF /* Build configuration list for PBXNativeTarget "CPPickerViewDemo" */; 158 | buildPhases = ( 159 | 0A3DA652147E3D9700143ADF /* Sources */, 160 | 0A3DA653147E3D9700143ADF /* Frameworks */, 161 | EA58F33D1881B90300204A7E /* Resources */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | ); 167 | name = CPPickerViewDemo; 168 | productName = PickerView; 169 | productReference = 0A3DA656147E3D9700143ADF /* CPPickerViewDemo.app */; 170 | productType = "com.apple.product-type.application"; 171 | }; 172 | /* End PBXNativeTarget section */ 173 | 174 | /* Begin PBXProject section */ 175 | 0A3DA64D147E3D9700143ADF /* Project object */ = { 176 | isa = PBXProject; 177 | attributes = { 178 | LastUpgradeCheck = 0500; 179 | }; 180 | buildConfigurationList = 0A3DA650147E3D9700143ADF /* Build configuration list for PBXProject "CPPickerViewDemo" */; 181 | compatibilityVersion = "Xcode 3.2"; 182 | developmentRegion = English; 183 | hasScannedForEncodings = 0; 184 | knownRegions = ( 185 | en, 186 | ); 187 | mainGroup = 0A3DA64B147E3D9700143ADF; 188 | productRefGroup = 0A3DA657147E3D9700143ADF /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | 0A3DA655147E3D9700143ADF /* CPPickerViewDemo */, 193 | ); 194 | }; 195 | /* End PBXProject section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | EA58F33D1881B90300204A7E /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | EA58F3411881B91E00204A7E /* ViewController.xib in Resources */, 203 | EA4BF4741881BA71002CB644 /* stretchableGlass@2x.png in Resources */, 204 | EA4BF4751881BA71002CB644 /* wheelBackground@2x.png in Resources */, 205 | EA4BF4731881BA71002CB644 /* shadowOverlay@2x.png in Resources */, 206 | EA58F3421881B91E00204A7E /* TableViewController.xib in Resources */, 207 | EA4BF47818820BB0002CB644 /* Default-568h@2x.png in Resources */, 208 | EA58F3431881B91E00204A7E /* InfoPlist.strings in Resources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXResourcesBuildPhase section */ 213 | 214 | /* Begin PBXSourcesBuildPhase section */ 215 | 0A3DA652147E3D9700143ADF /* Sources */ = { 216 | isa = PBXSourcesBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | EA6B58B41793168E00455D55 /* main.m in Sources */, 220 | EA6B58B31793166400455D55 /* CPPickerView.m in Sources */, 221 | 0A3DA66B147E3D9700143ADF /* AppDelegate.m in Sources */, 222 | 0A3DA66E147E3D9700143ADF /* ViewController.m in Sources */, 223 | EA5C7F901516717B0062E922 /* TableViewController.m in Sources */, 224 | EA5013431516D23C00917CFA /* CPPickerViewCell.m in Sources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | /* End PBXSourcesBuildPhase section */ 229 | 230 | /* Begin PBXVariantGroup section */ 231 | 0A3DA663147E3D9700143ADF /* InfoPlist.strings */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | 0A3DA664147E3D9700143ADF /* en */, 235 | ); 236 | name = InfoPlist.strings; 237 | path = ../CPPickerViewDemo; 238 | sourceTree = ""; 239 | }; 240 | 0A3DA66F147E3D9700143ADF /* ViewController.xib */ = { 241 | isa = PBXVariantGroup; 242 | children = ( 243 | 0A3DA670147E3D9700143ADF /* en */, 244 | ); 245 | name = ViewController.xib; 246 | path = ../CPPickerViewDemo; 247 | sourceTree = ""; 248 | }; 249 | /* End PBXVariantGroup section */ 250 | 251 | /* Begin XCBuildConfiguration section */ 252 | 0A3DA672147E3D9700143ADF /* Debug */ = { 253 | isa = XCBuildConfiguration; 254 | buildSettings = { 255 | ALWAYS_SEARCH_USER_PATHS = NO; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_BOOL_CONVERSION = YES; 258 | CLANG_WARN_CONSTANT_CONVERSION = YES; 259 | CLANG_WARN_EMPTY_BODY = YES; 260 | CLANG_WARN_ENUM_CONVERSION = YES; 261 | CLANG_WARN_INT_CONVERSION = YES; 262 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 263 | CODE_SIGN_IDENTITY = ""; 264 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 265 | COPY_PHASE_STRIP = NO; 266 | GCC_C_LANGUAGE_STANDARD = gnu99; 267 | GCC_DYNAMIC_NO_PIC = NO; 268 | GCC_OPTIMIZATION_LEVEL = 0; 269 | GCC_PREPROCESSOR_DEFINITIONS = ( 270 | "DEBUG=1", 271 | "$(inherited)", 272 | ); 273 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 274 | GCC_THUMB_SUPPORT = NO; 275 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 276 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 277 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 278 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 279 | GCC_WARN_UNDECLARED_SELECTOR = YES; 280 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 281 | GCC_WARN_UNUSED_FUNCTION = YES; 282 | GCC_WARN_UNUSED_VARIABLE = YES; 283 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 284 | ONLY_ACTIVE_ARCH = YES; 285 | SDKROOT = iphoneos; 286 | }; 287 | name = Debug; 288 | }; 289 | 0A3DA673147E3D9700143ADF /* Release */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | ALWAYS_SEARCH_USER_PATHS = NO; 293 | CLANG_ENABLE_OBJC_ARC = YES; 294 | CLANG_WARN_BOOL_CONVERSION = YES; 295 | CLANG_WARN_CONSTANT_CONVERSION = YES; 296 | CLANG_WARN_EMPTY_BODY = YES; 297 | CLANG_WARN_ENUM_CONVERSION = YES; 298 | CLANG_WARN_INT_CONVERSION = YES; 299 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 300 | CODE_SIGN_IDENTITY = ""; 301 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 302 | COPY_PHASE_STRIP = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu99; 304 | GCC_THUMB_SUPPORT = NO; 305 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 306 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 307 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 308 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 309 | GCC_WARN_UNDECLARED_SELECTOR = YES; 310 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 311 | GCC_WARN_UNUSED_FUNCTION = YES; 312 | GCC_WARN_UNUSED_VARIABLE = YES; 313 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 314 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 315 | SDKROOT = iphoneos; 316 | VALIDATE_PRODUCT = YES; 317 | }; 318 | name = Release; 319 | }; 320 | 0A3DA675147E3D9700143ADF /* Debug */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | CODE_SIGN_IDENTITY = "iPhone Developer"; 324 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 325 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 326 | GCC_PREFIX_HEADER = "CPPickerViewDemo/CPPickerViewDemo-Prefix.pch"; 327 | GCC_THUMB_SUPPORT = NO; 328 | INFOPLIST_FILE = "CPPickerViewDemo/CPPickerViewDemo-Info.plist"; 329 | PRODUCT_NAME = CPPickerViewDemo; 330 | PROVISIONING_PROFILE = ""; 331 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 332 | WRAPPER_EXTENSION = app; 333 | }; 334 | name = Debug; 335 | }; 336 | 0A3DA676147E3D9700143ADF /* Release */ = { 337 | isa = XCBuildConfiguration; 338 | buildSettings = { 339 | CODE_SIGN_IDENTITY = "iPhone Developer"; 340 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 341 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 342 | GCC_PREFIX_HEADER = "CPPickerViewDemo/CPPickerViewDemo-Prefix.pch"; 343 | GCC_THUMB_SUPPORT = NO; 344 | INFOPLIST_FILE = "CPPickerViewDemo/CPPickerViewDemo-Info.plist"; 345 | PRODUCT_NAME = CPPickerViewDemo; 346 | PROVISIONING_PROFILE = ""; 347 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 348 | WRAPPER_EXTENSION = app; 349 | }; 350 | name = Release; 351 | }; 352 | /* End XCBuildConfiguration section */ 353 | 354 | /* Begin XCConfigurationList section */ 355 | 0A3DA650147E3D9700143ADF /* Build configuration list for PBXProject "CPPickerViewDemo" */ = { 356 | isa = XCConfigurationList; 357 | buildConfigurations = ( 358 | 0A3DA672147E3D9700143ADF /* Debug */, 359 | 0A3DA673147E3D9700143ADF /* Release */, 360 | ); 361 | defaultConfigurationIsVisible = 0; 362 | defaultConfigurationName = Release; 363 | }; 364 | 0A3DA674147E3D9700143ADF /* Build configuration list for PBXNativeTarget "CPPickerViewDemo" */ = { 365 | isa = XCConfigurationList; 366 | buildConfigurations = ( 367 | 0A3DA675147E3D9700143ADF /* Debug */, 368 | 0A3DA676147E3D9700143ADF /* Release */, 369 | ); 370 | defaultConfigurationIsVisible = 0; 371 | defaultConfigurationName = Release; 372 | }; 373 | /* End XCConfigurationList section */ 374 | }; 375 | rootObject = 0A3DA64D147E3D9700143ADF /* Project object */; 376 | } 377 | -------------------------------------------------------------------------------- /CPPickerViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PickerView 4 | // 5 | // Created by Fraerman Arkady on 24.11.11. 6 | // Modified by Charles Powell on 3/19/12. 7 | // 8 | 9 | #import 10 | 11 | @class TableViewController; 12 | @class ViewController; 13 | 14 | @interface AppDelegate : UIResponder 15 | 16 | @property (strong, nonatomic) UIWindow *window; 17 | 18 | @property (strong, nonatomic) UITabBarController *viewController; 19 | @property (strong, nonatomic) TableViewController *tableViewController; 20 | @property (strong, nonatomic) ViewController *normalViewController; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /CPPickerViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PickerView 4 | // 5 | // Created by Fraerman Arkady on 24.11.11. 6 | // Modified by Charles Powell on 3/19/12. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | #import "TableViewController.h" 13 | 14 | @implementation AppDelegate 15 | 16 | @synthesize window = _window; 17 | @synthesize viewController = _viewController; 18 | @synthesize tableViewController = _tableViewController; 19 | @synthesize normalViewController = _normalViewController; 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 22 | { 23 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 24 | 25 | self.tableViewController = [[TableViewController alloc] initWithNibName:@"TableViewController" bundle:nil]; 26 | self.normalViewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 27 | 28 | self.tableViewController.title = @"Table Usage"; 29 | self.normalViewController.title = @"View Usage"; 30 | 31 | self.viewController = [[UITabBarController alloc] init]; 32 | NSMutableArray *controllers = [[NSMutableArray alloc] initWithCapacity:2]; 33 | [controllers addObject:self.tableViewController]; 34 | [controllers addObject:self.normalViewController]; 35 | 36 | self.viewController.viewControllers = controllers; 37 | 38 | [self.window addSubview:self.viewController.view]; 39 | [self.window makeKeyAndVisible]; 40 | return YES; 41 | } 42 | 43 | - (void)applicationWillResignActive:(UIApplication *)application 44 | { 45 | /* 46 | 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. 47 | 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. 48 | */ 49 | } 50 | 51 | - (void)applicationDidEnterBackground:(UIApplication *)application 52 | { 53 | /* 54 | 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. 55 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 56 | */ 57 | } 58 | 59 | - (void)applicationWillEnterForeground:(UIApplication *)application 60 | { 61 | /* 62 | 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. 63 | */ 64 | } 65 | 66 | - (void)applicationDidBecomeActive:(UIApplication *)application 67 | { 68 | /* 69 | 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. 70 | */ 71 | } 72 | 73 | - (void)applicationWillTerminate:(UIApplication *)application 74 | { 75 | /* 76 | Called when the application is about to terminate. 77 | Save data if appropriate. 78 | See also applicationDidEnterBackground:. 79 | */ 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /CPPickerViewDemo/CPPickerViewDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | com.charlespowell.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /CPPickerViewDemo/CPPickerViewDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PickerView' target in the 'PickerView' 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 -------------------------------------------------------------------------------- /CPPickerViewDemo/TableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.h 3 | // PickerView 4 | // 5 | // Created by Charles Powell on 3/18/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "CPPickerViewCell.h" 12 | 13 | @interface TableViewController : UITableViewController 14 | 15 | @property (strong, nonatomic) NSMutableArray *settingsStorage; 16 | 17 | @property (nonatomic, strong) IBOutlet UILabel *sectionOneLabel; 18 | @property (nonatomic, strong) IBOutlet UILabel *sectionTwoLabel; 19 | 20 | @end -------------------------------------------------------------------------------- /CPPickerViewDemo/TableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.m 3 | // PickerView 4 | // 5 | // Created by Charles Powell on 3/18/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "TableViewController.h" 10 | 11 | #import "CPPickerViewCell.h" 12 | 13 | @interface TableViewController () 14 | 15 | @end 16 | 17 | @implementation TableViewController 18 | 19 | @synthesize settingsStorage; 20 | 21 | - (id)initWithStyle:(UITableViewStyle)style 22 | { 23 | self = [super initWithStyle:style]; 24 | if (self) { 25 | // Custom initialization 26 | } 27 | return self; 28 | } 29 | 30 | - (void)viewDidLoad 31 | { 32 | [super viewDidLoad]; 33 | 34 | self.title = @"Table Usage"; 35 | NSArray *section1 = [NSMutableArray arrayWithObjects:[NSNumber numberWithInteger:0], nil]; 36 | NSArray *section2 = [NSMutableArray arrayWithObjects:[NSNumber numberWithInteger:1], nil]; 37 | self.settingsStorage = [NSMutableArray arrayWithObjects:section1, section2, nil]; 38 | 39 | [self setLabelTextForSection:0 forItem:0]; 40 | [self setLabelTextForSection:1 forItem:1]; 41 | } 42 | 43 | - (void)viewDidUnload 44 | { 45 | [super viewDidUnload]; 46 | 47 | self.settingsStorage = nil; 48 | } 49 | 50 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 51 | { 52 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 53 | } 54 | 55 | - (void)setLabelTextForSection:(NSUInteger)section forItem:(NSUInteger)item 56 | { 57 | switch (section) { 58 | case 0: 59 | // Section 1 60 | self.sectionOneLabel.text = [NSString stringWithFormat:@"Section 1: Option %i", item + 1]; 61 | break; 62 | 63 | case 1: 64 | // Section 2 65 | self.sectionTwoLabel.text = [NSString stringWithFormat:@"Section 2: %i", item + 1]; 66 | break; 67 | 68 | default: 69 | break; 70 | } 71 | } 72 | 73 | #pragma mark - Table view data source 74 | 75 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 76 | return [NSString stringWithFormat:@"Section %i", section + 1]; 77 | } 78 | 79 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 80 | { 81 | return 2; 82 | } 83 | 84 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 85 | { 86 | return 1; 87 | } 88 | 89 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 90 | { 91 | static NSString *CellIdentifier = @"Cell"; 92 | CPPickerViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 93 | 94 | if (cell == nil) { 95 | cell = [[CPPickerViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 96 | } 97 | 98 | cell.textLabel.text = @"Multi-option picker"; 99 | 100 | cell.dataSource = self; 101 | cell.delegate = self; 102 | cell.currentIndexPath = indexPath; 103 | 104 | [cell reloadData]; 105 | 106 | 107 | // Configure/Reconfigure 108 | NSInteger section = indexPath.section; 109 | NSInteger row = indexPath.row; 110 | 111 | if (section == 1) { 112 | cell.showGlass = YES; 113 | cell.peekInset = UIEdgeInsetsMake(0, 35, 0, 35); 114 | } 115 | 116 | NSArray *sectionStorage = [self.settingsStorage objectAtIndex:section]; 117 | NSUInteger setting = [[sectionStorage objectAtIndex:row] unsignedIntegerValue]; 118 | 119 | [cell setSelectedItem:setting animated:NO]; 120 | 121 | return cell; 122 | } 123 | 124 | #pragma mark - Table view delegate 125 | 126 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 127 | { 128 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 129 | } 130 | 131 | #pragma mark - CPPickerViewCell DataSource 132 | 133 | - (NSInteger)numberOfItemsInPickerViewAtIndexPath:(NSIndexPath *)pickerPath { 134 | if (pickerPath.section == 0) { 135 | return 4; 136 | } 137 | 138 | if (pickerPath.section == 1) { 139 | return 10; 140 | } 141 | 142 | return 0; 143 | } 144 | 145 | - (NSString *)pickerViewAtIndexPath:(NSIndexPath *)pickerPath titleForItem:(NSInteger)item { 146 | if (pickerPath.section == 0) { 147 | return [NSString stringWithFormat:@"Option %i", item + 1]; 148 | } 149 | 150 | if (pickerPath.section == 1) { 151 | return [NSString stringWithFormat:@"%i", item + 1]; 152 | } 153 | 154 | return nil; 155 | } 156 | 157 | #pragma mark - CPPickerViewCell Delegate 158 | 159 | - (void)pickerViewAtIndexPath:(NSIndexPath *)pickerPath didSelectItem:(NSInteger)item { 160 | [[self.settingsStorage objectAtIndex:pickerPath.section] replaceObjectAtIndex:pickerPath.row withObject:[NSNumber numberWithInt:item]]; 161 | 162 | [self setLabelTextForSection:pickerPath.section forItem:item]; 163 | } 164 | 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /CPPickerViewDemo/TableViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 32 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /CPPickerViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // PickerView 4 | // 5 | // Created by Fraerman Arkady on 24.11.11. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CPPickerView.h" 11 | 12 | @interface ViewController : UIViewController 13 | 14 | @property (nonatomic, strong) CPPickerView *defaultPickerView; 15 | @property (nonatomic, strong) CPPickerView *daysPickerView; 16 | 17 | @property (nonatomic, strong) NSArray *daysData; 18 | 19 | @property (strong, nonatomic) IBOutlet UILabel *numberLabel; 20 | @property (strong, nonatomic) IBOutlet UILabel *dayLabel; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /CPPickerViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // PickerView 4 | // 5 | // Created by Fraerman Arkady on 24.11.11. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @implementation ViewController 12 | 13 | #pragma mark - Synthesizatoin 14 | 15 | @synthesize numberLabel; 16 | @synthesize dayLabel; 17 | 18 | 19 | 20 | 21 | #pragma mark - View lifecycle 22 | 23 | - (void)viewDidLoad 24 | { 25 | [super viewDidLoad]; 26 | 27 | self.title = @"View Usage"; 28 | 29 | self.daysData = [[NSArray alloc] initWithObjects:@"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday", @"Sunday", nil]; 30 | 31 | self.defaultPickerView = [[CPPickerView alloc] initWithFrame:CGRectMake(85, 30.0, 150, 40)]; 32 | self.defaultPickerView.backgroundColor = [UIColor whiteColor]; 33 | self.defaultPickerView.dataSource = self; 34 | self.defaultPickerView.delegate = self; 35 | self.defaultPickerView.allowSlowDeceleration = YES; 36 | [self.defaultPickerView reloadData]; 37 | [self.view addSubview:self.defaultPickerView]; 38 | } 39 | 40 | #pragma mark - CPPickerViewDataSource 41 | 42 | - (NSInteger)numberOfItemsInPickerView:(CPPickerView *)pickerView 43 | { 44 | return 200; 45 | } 46 | 47 | 48 | 49 | 50 | - (NSString *)pickerView:(CPPickerView *)pickerView titleForItem:(NSInteger)item 51 | { 52 | return [NSString stringWithFormat:@"%i", item + 1]; 53 | } 54 | 55 | 56 | 57 | 58 | #pragma mark - CPPickerViewDelegate 59 | 60 | - (void)pickerView:(CPPickerView *)pickerView didSelectItem:(NSInteger)item 61 | { 62 | self.numberLabel.text = [NSString stringWithFormat:@"%i", item + 1]; 63 | } 64 | 65 | 66 | 67 | 68 | #pragma mark - Memory Management 69 | 70 | - (void)didReceiveMemoryWarning 71 | { 72 | [super didReceiveMemoryWarning]; 73 | // Release any cached data, images, etc that aren't in use. 74 | } 75 | 76 | 77 | 78 | 79 | - (void)viewDidUnload 80 | { 81 | [self setNumberLabel:nil]; 82 | [self setDayLabel:nil]; 83 | [super viewDidUnload]; 84 | // Release any retained subviews of the main view. 85 | // e.g. self.myOutlet = nil; 86 | } 87 | 88 | 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /CPPickerViewDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /CPPickerViewDemo/en.lproj/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 26 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /CPPickerViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PickerView 4 | // 5 | // Created by Fraerman Arkady on 24.11.11. 6 | // Copyright (c) 2011 __MyCompanyName__. 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 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbpowell/CPPickerView/c4a55e3eaf5afb9267a82d6cc84e0fbe5995ca62/Default-568h@2x.png -------------------------------------------------------------------------------- /Image Resources/Graphics.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbpowell/CPPickerView/c4a55e3eaf5afb9267a82d6cc84e0fbe5995ca62/Image Resources/Graphics.psd -------------------------------------------------------------------------------- /Image Resources/StretchableGlass.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbpowell/CPPickerView/c4a55e3eaf5afb9267a82d6cc84e0fbe5995ca62/Image Resources/StretchableGlass.psd -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013 Charles Powell 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 4 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 5 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 6 | to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 11 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 13 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 14 | IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | A custom, configurable, horizontal version of UIPickerView. 4 | 5 | Also included is CPPickerViewCell, a UITableViewCell sublcass that adds a CPPickerView to the right side of the cell. This cell was envisioned for a settings-type view, allowing a multi-option setting to be handled in a single table row (whereas normally it would require a disclosure or multiple rows). 6 | 7 | If you're interested in a vertical custom UIPickerView controller, check out [AFPickerView](https://github.com/arkichek/AFPickerView) by Arkady Fraerman! This code is essentially forked from his project. 8 | 9 | ![CPPickerView screenshot](http://cbpowell.github.com/CPPickerView/screenshot.png) 10 | 11 | CPPickerView is currently in use by at least one approved app in the App Store (Hipmunk for iPhone/iPad!). 12 | 13 | ## Usage 14 | 15 | ### General 16 | 17 | To customize the appearance, replace the following images with your own: 18 | 19 | * wheelBackground.png 20 | * stretchableGlass.png 21 | * shadowOverlay.png 22 | 23 | __NOTE__: CPPickerView uses `- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets` (for iOS 5.0 and up) or `- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets` (for below iOS 5.0) to stretch _wheelBackground.png_ and _stretchableGlass.png_. Be sure to look at the sample images in relation to the cap sizes set in CPPickerView.m's `initWithFrame:` before changing the sizing of the images, as you may need to adjust the caps. _shadowOverlay.png_ is currently simply stretched to fit the frame. 24 | 25 | Several appearance options are settable via properties: 26 | 27 | * `BOOL showGlass` - defines whether or not to show the "glass" overlay over the selected item. 28 | * `UIEdgeInsets peekInset` - defines the amount the item to the left and right of the currently selected item "peek" into view. This can be used as an indication to the user that there are other items, if desired. _NOTE_: You most likely want to leave the `top` and `bottom` inset values at 0, and adjust the `left` and `right` values. Larger inset values mean more peek. 29 | 30 | 31 | You can also enable/disable the ability for the user to change the picker via the `enabled` property. The default state is `YES`. 32 | 33 | ### Standard Usage 34 | Create a CPPickerView instance and configure it: 35 | 36 | ```objective-c 37 | pickerView = [[CPPickerView alloc] initWithFrame:CGRectMake(30.0, 250.0, 126.0, 197.0)]; 38 | pickerView.rowFont = [UIFont boldSystemFontOfSize:19.0]; 39 | pickerView.rowIndent = 10.0; 40 | pickerView.showGlass = YES; 41 | ``` 42 | 43 | Set the dataSource, delegate, and call `[pickerView reloadData]`: 44 | 45 | ```objective-c 46 | pickerView.dataSource = self; 47 | pickerView.delegate = self; 48 | [pickerView reloadData]; 49 | ``` 50 | 51 | Then implement CPPickerViewDataSource and CPPickerViewDelegate in your controller. 52 | 53 | ### CPPickerViewCell Usage 54 | 55 | Use CPPickerViewCell like a normal UITableViewCell. Inside `tableView:cellForRowAtIndexPath:`, dequeue or create the cell: 56 | 57 | ```objective-c 58 | CPPickerViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 59 | if (cell == nil) { 60 | cell = [[CPPickerViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 61 | } 62 | ``` 63 | 64 | Set the data source and the delegate for the cell, and inform it of it's index path: 65 | 66 | ```objective-c 67 | cell.dataSource = self; 68 | cell.delegate = self; 69 | cell.currentIndexPath = indexPath; 70 | ``` 71 | 72 | __NOTE__: CPPickerViewCells MUST be informed of their index path in the table, or you won't be able to distinguish between them in your datasource and delegate methods! 73 | 74 | And implement CPPickerViewCellDataSource and CPPickerViewCellDelegate per the protocols. In the included example the TableViewController (i.e. `self`) is set up as the data source and delegate for all cells. 75 | 76 | The data source/delegate methods for `CPPickerViewCell` convert the normal `CPPickerView` data source/delegate methods to refer to the requests for data by NSIndexPath rather than the CPPickerView object (to match the typical way table cells are identified). 77 | 78 | Finally, reload the cell (aka the CPPickerView, the items in the picker will be requested again) and then reconfigure it with any specific settings for the given row if you're recalling some previously stored settings. Then return the cell. 79 | 80 | ```objective-c 81 | [cell reloadData]; 82 | // Reconfigure 83 | cell.showGlass = YES; 84 | cell.peekInset = UIEdgeInsetsMake(0, 18, 0, 18); 85 | NSInteger *storedSelectedIndex = [[AnArrayOfStoredStuff objectAtIndex:indexPath.row] intValue]; 86 | [cell selectItemAtIndex:storedSelectedIndex animated:NO]; //Unanimated, because this should be immediate 87 | return cell; 88 | ``` 89 | 90 | ## Todo 91 | - Any ideas? 92 | 93 | ## About 94 | 95 | Charles Powell 96 | - [GitHub](http://github.com/cbpowell) 97 | - [Twitter](http://twitter.com/seventhcolumn) 98 | 99 | Give me a shout if you're using this in your project! 100 | -------------------------------------------------------------------------------- /Resources/shadowOverlay@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbpowell/CPPickerView/c4a55e3eaf5afb9267a82d6cc84e0fbe5995ca62/Resources/shadowOverlay@2x.png -------------------------------------------------------------------------------- /Resources/stretchableGlass@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbpowell/CPPickerView/c4a55e3eaf5afb9267a82d6cc84e0fbe5995ca62/Resources/stretchableGlass@2x.png -------------------------------------------------------------------------------- /Resources/wheelBackground@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbpowell/CPPickerView/c4a55e3eaf5afb9267a82d6cc84e0fbe5995ca62/Resources/wheelBackground@2x.png --------------------------------------------------------------------------------