A custom, configurable, horizontal version of UIPickerView.
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).
If you're interested in a vertical custom UIPickerView controller, check out AFPickerView by Arkady Fraerman! This code is essentially forked from his project.
CPPickerView is currently in use by at least one approved app in the App Store (Hipmunk for iPhone/iPad!).
To customize the appearance, replace the following images with your own:
- wheelBackground.png
- stretchableGlass.png
- shadowOverlay.png
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.
Several appearance options are settable via properties:
BOOL showGlass
- defines whether or not to show the "glass" overlay over the selected item.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 thetop
andbottom
inset values at 0, and adjust theleft
andright
values. Larger inset values mean more peek.
You can also enable/disable the ability for the user to change the picker via the enabled
property. The default state is YES
.
Create a CPPickerView instance and configure it:
pickerView = [[CPPickerView alloc] initWithFrame:CGRectMake(30.0, 250.0, 126.0, 197.0)];
pickerView.rowFont = [UIFont boldSystemFontOfSize:19.0];
pickerView.rowIndent = 10.0;
pickerView.showGlass = YES;
Set the dataSource, delegate, and call [pickerView reloadData]
:
pickerView.dataSource = self;
pickerView.delegate = self;
[pickerView reloadData];
Then implement CPPickerViewDataSource and CPPickerViewDelegate in your controller.
Use CPPickerViewCell like a normal UITableViewCell. Inside tableView:cellForRowAtIndexPath:
, dequeue or create the cell:
CPPickerViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CPPickerViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Set the data source and the delegate for the cell, and inform it of it's index path:
cell.dataSource = self;
cell.delegate = self;
cell.currentIndexPath = indexPath;
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!
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.
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).
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.
[cell reloadData];
// Reconfigure
cell.showGlass = YES;
cell.peekInset = UIEdgeInsetsMake(0, 18, 0, 18);
NSInteger *storedSelectedIndex = [[AnArrayOfStoredStuff objectAtIndex:indexPath.row] intValue];
[cell selectItemAtIndex:storedSelectedIndex animated:NO]; //Unanimated, because this should be immediate
return cell;
- Any ideas?
Charles Powell
Give me a shout if you're using this in your project!