The context
Object UISegmentedControl may be used to act as a tab bar in order to navigate between views, or to act a selector between many choices. In the case of a UISegmentedControl with UISegmentedControlStyleBar style, the selected segment is only darker than the unselected ones. Depending on the control's tint color, the distinction may be difficult to see (example below).

The goal of this post is to show that with a few code, it's possible to obtain an other behavior, with a selected segment differently colored than the others (example below)

The code
First of all, you'll find at the end of this post a zip archive containing an XCode project with the code used for this post. From now until the end of this post, you'll have to keep the following elements in mind:
- UISegmentedControl object must use UISegmentedControlStyleBar style (mandatory).
- A selector on “Value Changed” points on the method “-(IBAction)selectSegment:(id)sender” (adapt to fit your needs).
You have to append to the class where you use UISegmentedControl object a function which sorts UIView by their horizontal coordinates:
NSInteger static compareViewsByOrigin(id sp1, id sp2, void *context) { // UISegmentedControl segments use UISegment objects (private API). But we can safely cast them to UIView objects. float v1 = ((UIView *)sp1).frame.origin.x; float v2 = ((UIView *)sp2).frame.origin.x; if (v1 < v2) return NSOrderedAscending; else if (v1 > v2) return NSOrderedDescending; else return NSOrderedSame; }
Then, append to “-(IBAction)selectSegment:(id)sender” method the following code:
// Get number of segments int numSegments = [betterSegmentedControl.subviews count]; // Reset segment's color (non selected color) for( int i = 0; i < numSegments; i++ ) { // reset color [[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:nil]; [[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:[UIColor colorWithRed:200/255.0 green:200/255.0 blue:200/255.0 alpha:1]]; } // Sort segments from left to right NSArray *sortedViews = [betterSegmentedControl.subviews sortedArrayUsingFunction:compareViewsByOrigin context:NULL]; // Change color of selected segment [[sortedViews objectAtIndex:betterSegmentedControl.selectedSegmentIndex] setTintColor:[UIColor colorWithRed:255/255.0 green:0/255.0 blue:0/255.0 alpha:1]]; // Remove all original segments from the control for (id view in betterSegmentedControl.subviews) { [view removeFromSuperview]; } // Append sorted and colored segments to the control for (id view in sortedViews) { [betterSegmentedControl addSubview:view]; }
And that's all !
Twitter
Facebook
Google+
LinkedIn
Commentaires
Great Tutorial! However I am struggling to understand how can I manage in the viewDidLoad method to present the segmented Control with the first option selected. Since it is tied to an action, is this possible? And on the contrary, how can I reset everything to grey and not selected when loading another view. SO that when I return to the same view, I appears again in gray?
naShHi !
To select the first segment, you just to use
Arnaud BoudouTo have no selected segment :