Mac OS X Reference Library Apple Developer
Search

Using Segmented Controls

You can create and configure a segmented control programatically or using Interface Builder. You can also interact with the control programatically, for example to set the selection, and to enable and disable segments.

Creating and Configuring a Segmented Control

There are a number of aspects of a segmented control that you should configure: its tracking mode—the way in which selections are handled; how many segments it contains; and the properties of each segment. Segmented controls support three different tracking modes, specified by the following constants:

NSSegmentSwitchTrackingSelectOne

Only one button can be selected

NSSegmentSwitchTrackingSelectAny

Any button can be selected

NSSegmentSwitchTrackingMomentary

Segments are selected only while tracking

Configuring a Segmented Control in Interface Builder

The easiest way to create a segmented control is in Interface Builder. To do so, simply drag a segmented control from the Cocoa-Controls palette to your window. Use the Attributes panes of the Inspector window to configure the attributes of the segmented control. These are:

Certain attributes must be configured individually for each segment. To configure a segment, double-click to select it. The Inspector window for an NSSegmentedCell lets you configure these attributes:

Configuring a Segmented Control Programatically

You can also create a segmented control programmatically. One of the simplest applications of a segmented control is its use as a compact alternative to a group of radio buttons. Here, the user makes a single selection from a number of options. Listing 1 shows code to create a control like one found in iPhoto.

Listing 1  Simple text-based example

// Set the number of segments
[segControl setSegmentCount:4];
// Set titles for each segment
[segControl setLabel:@"Import" forSegment:0];
[segControl setLabel:@"Organize" forSegment:1];
[segControl setLabel:@"Edit" forSegment:2];
[segControl setLabel:@"Book" forSegment:3];

By default a segmented control autosizes to fit. To programatically mark a segment as autosizing, set its width to 0. If any segments are marked as autosizing, then the widths are adjusted so that all segments are displayed completely in the control.

If you want to ensure a fixed size, perhaps with each segment the same width, you must set the width of each segment individually, as shown in Listing 2.

Listing 2  Setting segments to equal widths

[segControl setWidth:70 forSegment:0];
[segControl setWidth:70 forSegment:1];
[segControl setWidth:70 forSegment:2];
[segControl setWidth:70 forSegment:3];

Combining code from Listing 1 and Listing 2 produces a controller like that shown in Figure 1.

Figure 1  Control with segments of equal width

Control with segments of equal width

It is up to you to ensure that each segment is wide enough for its contents. If an image is too large to fit, it is clipped on the right. If the text, or the combination of the text and image, is too wide for a segment, the text is truncated using an ellipsis.

Some of the methods you may require for configuration (for example the tracking mode) are implemented only in NSSegmentedCell, so you must access the control’s cell, as in the following example:

[[segControl cell] setTrackingMode:NSSegmentedSwitchTrackingSelectAny];

In common with other controls, NSSegmentedControl is available in three sizes—regular, small, and mini (although textured windows only support regular-sized segmented controls). The size is also configured by the cell:

[[segControl cell] setControlSize:NSMiniControlSize];

Combining Segments With Different Attributes

There is no requirement that all segments within a segmented control be of the same type. The following code creates a segmented control like that found in iCal, as illustrated in Figure 2:

[segControl setSegmentCount:5];
// Configure each segment
[segControl setImage:MYLeftArrowImage forSegment:0];
[segControl setLabel:@"Day" forSegment:1];
[segControl setLabel:@"Week" forSegment:2];
[segControl setLabel:@"Month" forSegment:3];
[segControl setImage:MYRightArrowImage forSegment:4];

Figure 2  Segmented control showing a combination of segment types

Segmented control showing a combination of segment types

Note: In Interface Builder, you can edit the label and image for each segment independently, as described in ‚ÄúConfiguring a Segmented Control in Interface Builder.‚Äù

It is not possible, however, to specify different tracking modes for different segments. You cannot specify momentary selection for some segments and radio button behavior for others. Thus, although the control in Figure 2looks like one found in iCal, it cannot function in the same way (that is, where the arrows are selected momentarily and advance through the calendar, and one of the text buttons remains continuously selected to choose the display option). The exception to this rule is a segment that contains a menu. A segment with a menu always acts as a momentary control and cannot be toggled on, even if the control is configured as “select one” or “select any”.

Although it is possible to set both a label and an image for a segment, a segment should have one or the other, as described in Apple Human Interface Guidelines.

Note: In Mac OS X v10.4 and earlier, images are not automatically centered in the segment. To ensure that a segment's image is centered, use the following workaround:

[segmentedControl setLabel: nil forSegment: n];

Interacting With a Segmented Control

There are a number of methods for interacting with a segmented control programatically—for example, to change the selected segment, and to enable and disable individual segments.

You can find out which segment, if any, is selected, using selectedSegment. If no segment is selected, the method returns –1. When a control is configured to allow multiple selections, you can find out if an individual segment is selected using isSelectedForSegment:. Conversely, you can set the selection using setSelectedSegment: and setSelected:forSegment:.

Similarly, you can enable and disable individual segments within the control using setEnabled:forSegment:. Doing so may be useful to restrict the user to making selections that are valid for the current environment, as illustrated below.

image: ../Art/disabledsegments-1.gif

Tags and Target-Action

As with any control, you can set a segmented control's target, action, and tag. Each segment within the control, however, may have its own tag. When any segment in the control is clicked, the action message is sent to the target—unless the segment is disabled or has a menu. You can determine which segment was clicked by finding the tag for the selected segment, as shown in the following example:

- (void)awakeFromNib
{
    [segControl setSegmentCount:3];
    [[segControl cell] setTag:0 forSegment:0];
    [[segControl cell] setTag:1 forSegment:1];
    [[segControl cell] setTag:2 forSegment:2];
    [segControl setTarget:self];
    [segControl setAction:@selector(segControlClicked:)];
}
 
- (IBAction)segControlClicked:(id)sender
{
    int clickedSegment = [sender selectedSegment];
    int clickedSegmentTag = [[sender cell] tagForSegment:clickedSegment];
    //...
}

Note that the cell’s selectedSegment method returns the segment that was last clicked. This means you can find out which segment was clicked, even when tracking mode is NSSegmentSwitchTrackingSelectAny or NSSegmentSwitchTrackingMomentary. Note also that if a segment contains a menu, the action message is not sent when it is clicked.




Last updated: 2006-02-07

Did this document help you? Yes It's good, but... Not helpful...