iOS7 UIPickerView Customization
The iOS UIPickerView is one SDK component that leaves little to the developer for customization. With iOS7 and its entirely revamped look and feel just around the corner (allegedly), you may think that you’ll be stuck with the new and improved UIPickerView chrome which for many may feel sub-optimal for existing or new apps that use this control. Help is just a delegate method away.
First some good news. If you have an app on the App Store built with the iOS6 SDK, it will run under iOS7 just fine and look just as you designed it for iOS6. It won’t be until you re-build your app against the iOS7 SDK that you’ll start seeing the effects of the iOS7 UI makeover.
That being said, one element in the iOS7 SDK whose restyling you may want to suppress is UIPickerView. To wit, compare the standard iOS6 UIPickerView with it’s iOS7 counterpart:
You can see that the default styling is pretty different between the two SDKs. The code to generate the data in each case uses the same basic delegate method:
[code lang=”objc”]
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [NSString stringWithFormat:@"%d", row+1];
}
[/code]
What if you want to achieve something closer to the iOS6 look in iOS7? Easy! Switch delegate methods. As with UITableView section headers and footers, there is a UIView version of the above delegate method for UIPickerView. Using it, we can achieve almost any look (for the picker rows) we want, for example:
Here’s the code. Instead of the previous delegate method, I used this:
[code lang=”objc”]
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, 44)];
label.backgroundColor = [UIColor lightGrayColor];
label.textColor = [UIColor blackColor];
label.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:18];
label.text = [NSString stringWithFormat:@" %d", row+1];
return label;
}
[/code]
The point is that you can provide your own views for each row of the picker, rather than just a string value for which UIPickerView does it’s default styling. This is not a new thing; this has always been a capability of UIPickerView. Providing your own view is a little more work, of course, but gives you as much control as you feel you can wrench away from the SDK.
Clearly, I have not duplicated the iOS6 look under iOS7 here! But you can see that with a little bit of work (and by tweaking certain properties of UIPickerView that we do have access to), you can achieve your own look. You’re not entirely forced into the iOS7 chrome.
iOS7’s visual redesign goes beyond simple visual changes. In my work I’ve been discovering various semantic changes Apple has made under the hood as well. There’s a reason most every iOS developer has been hard at work since June. We’ll see soon if those labors pay off.
Finally, the same information i was looking for from hours. Have a question, what if we want to move all the same from numbers to alphabets.
Easy:
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return 26; // 26 letters in the alphabet
}
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, 44)];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor blackColor];
label.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:18];
label.text = [NSString stringWithFormat:@" %c", 65+row]; // ASCII 65 is "A"
return label;
}
Thank you!
Cool, thanks. This picker is tricky indeed. Also if you want to center the numbers, here’s the code:
UILabel *label = [[UILabel alloc] init];
[label setTextAlignment:NSTextAlignmentCenter];