Customizing the colors of a UISegmentedControl Customizing the colors of a UISegmentedControl ios ios

Customizing the colors of a UISegmentedControl


UISegmentedControl has a tintColor property -- this allows you to change what color the control is, but not the general "style" (the rounded, beveled shape):

segmentedControl.tintColor = [UIColor blueColor];

As for creating UIImages on the fly, you can create a CGContext, do whatever drawing you need to in that context (including strings), and then get a UIImage out of the context's CGImage:

CGContextRef drawContext = CGBitmapContextCreate(<many parameters>);//do drawing hereCGImageRef finalImage = CGBitmapContextCreateImage(drawContext);UIImage *cellImage = [UIImage finalImage];

Please note, that if you use code like UIView.appearance().tintColor = .myColor (or equiv. in ObjC), the effect most likely won't take place.


segmentedControl.tintColor = [UIColor colorWithRed:0.61176f green:0.61176f  blue:0.61176f  alpha:1.0f];segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;


Most of the answers here don't answer the specific question of how to set a button color based on selected state which implies another color is desired for unselected state. I struggled with this for quite some time and wanted to share my solution for others to use.

My example uses a UISegmentedControl with three segments. The unselected color for all three should be the same to give it a uniform look. The selected state for the first and last segment have unique colors.

enter image description here

The issue is that the segmented control is not guaranteed to be in the same order so the colors will get mixed up as you select back and forth. Dan posted a solution that uses tags but unfortunately it's no longer guaranteed to work for iOS 6 and up.

Most of this code is taken from this post. I changed it slightly to have unique selected colors.

What makes it work is the sorting but take note of these 2 important lines for setting the selected color:

NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;[[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];

- (void) updateSegmentColors{    UIColor *checkColor = [UIColor colorWithRed: 29/255.0 green:166/255.0 blue:47/255.0 alpha:1.0];    NSArray *segmentColors = [[NSArray alloc] initWithObjects:checkColor, [UIColor blueColor], [UIColor redColor], nil];    UISegmentedControl *betterSegmentedControl = self.StatusControl;    // Get number of segments    NSUInteger 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 blueColor]];    }    // Sort segments from left to right    NSArray *sortedViews = [betterSegmentedControl.subviews sortedArrayUsingFunction:compareViewsByOrigin context:NULL];    // Change color of selected segment    NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;    [[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];    // 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];    }}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;}

I placed the code in it's own method because I'm loading these segmented controls in a table view and need to run it upon loading (existing states from storage) and when a user changes a selection. Now I just need to call [Self updateSegmentColors]; when something changes.