4. Tables and Pickers
The UITableView and
UIPickerView classes display lists of values to
users. Neither class is a descendant of
UIControl, but both are useful as input interfaces.
You can use cells in tables to show a list of options that accepts
multiple concurrent choices. A picker view is a good option for showing
a list that accepts only one selection at a time.
Tables are often used to display lists of items with a selectable
cell for each possible value. Tables are excellent options for
displaying long, one-dimensional lists or lists with groups of smaller,
related lists. You should consider using a
UITableView when the values in your dataset aren’t
known or intuitive to users. Finite ordered sets that users recognize,
such as the names of months or hours in the day, can be displayed using
controls that require less screen area because users can easily infer
the values that are offscreen based on the visible at any moment
elements. Tables can display items from a large set, giving more context
and allowing faster scrolling and indexing (using an index ribbon). The
Ringtones screen in the Contacts application uses a standard UITableView with groups of selectable
cells, as shown in Figure 6.
Like UITableView,
UIPickerView is not a descendant of
UIControl but acts as a user input control. You’ve
seen pickers used in the Clock, Calendar, and Mail applications, among
others. Most UIKit controls are metaphors for
real-world interfaces. Buttons, sliders, and switches all mimic the
behavior of a physical interface element. The hardware version of a
UIPickerView is a group of vertically spinning dials
reminiscent of a classic slot machine interface.
Figure 7 shows a simple picker from the
UICatalog application included in the iPhone SDK
examples.
Unlike UITableView instances, pickers can
display multidimensional data as vertically parallel lists. For example,
consider the UIDatePicker class included in
UIKit. Users can choose date components individually
when setting a date in a UIDatePicker. Depending on
the mode of operation assigned to a date picker instance, the interface
will display one of the following sets of components:
For UIDatePickerModeTime, the picker
will display hours, minutes, and (optionally) an AM/PM selection
component. The order of the components depends on global
localization contexts.
For UIDatePickerModeDate, the picker
will display months, days of the month, and years.
For UIDatePickerModeDateAndTime, the
picker displays dates (in one component), hours, minutes, and
(optionally) an AM/PM selection component.
For UIDatePickerModeCountdownTimer, the
picker displays hour and minute values representing an interval for
a countdown.
You can retrieve the mode for a UIDatePicker
instance using its datePickerMode
property.
When working with a UIPickerView, you should
follow the conventions outlined by Apple for displaying values. You
should avoid listing units in a value component except when the unit
type is the value. For example, the AM/PM selection component displayed
by the UIDatePicker class is appropriate because both
“AM” and “PM” are values. In cases where you’d like to display a set of
non-value units for a component, you can use a non-standard approach to
build the display. There are safer methods, but this approach provides a
quick proof of concept:
#import "LabeledPickerView.h"
@interface _UIPickerViewSelectionBar : UIView
@end
@implementation LabeledPickerView
- (void)drawRect:(CGRect)rect
{
// Draw the label if it needs to be drawn
if(fixedLabel == nil){
fixedLabel = [[UILabel alloc]
initWithFrame:CGRectMake(0.0, 0.0, 200.0, 40.0)];
fixedLabel.font = [UIFont boldSystemFontOfSize:20.0];
fixedLabel.textColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
fixedLabel.backgroundColor = [UIColor clearColor];
fixedLabel.shadowColor = [UIColor whiteColor];
fixedLabel.shadowOffset = CGSizeMake(0, 1);
fixedLabel.text = @"...is tasty.";
NSArray *svs = [self subviews];
UIView *v;
for(v in svs){
if([v isKindOfClass:[_UIPickerViewSelectionBar class]]){
CGPoint c = CGPointMake(v.center.x + 40.0, v.center.y - 86);
fixedLabel.center = c;
[v addSubview:fixedLabel];
return;
}
}
}
}
- (void)dealloc
{
[fixedLabel release];
[super dealloc];
}
@end
The key operation is in the search for an instance of
_UIPickerViewSelectionBar and the addition of a
custom UILabel instance as a subview to the selection
bar. The result can be seen in Figure 8.