Been looking around and trying to change just the border color (with a different text color) with no luck. Can change the tint, but changes both the text and border.
6 Answers
You can use UIAppearance proxy to set title text attributes but preserve tintColor for borders. Something like:
[[UISegmentedControl appearance] setTitleTextAttributes:@{
NSForegroundColorAttributeName : [UIColor redColor]
} forState:UIControlStateNormal];
Edit:
To tint images, you can use something like this in category on UImage:
- (instancetype)tintedImageWithColor:(UIColor *)tintColor {
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rect = (CGRect){ CGPointZero, self.size };
CGContextSetBlendMode(context, kCGBlendModeNormal);
[self drawInRect:rect];
CGContextSetBlendMode(context, kCGBlendModeSourceIn);
[tintColor setFill];
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

- 2,557
- 23
- 23
-
3So nicely done. Quick, correct answer. Please people, Plus this answer. – ort11 Sep 27 '13 at 22:17
-
2I would say my answer here is a more correct solution. Feel free to take a look :) – OscarWyck Oct 26 '13 at 08:35
-
1Would only work if you use text in your segmented control. When the items are images, they become tinted to the same color as the borders and this approach wouldn't help. – ilmiacs Feb 17 '14 at 10:30
-
That's right. But it's fairly easy to tint images manually, I have updated my answer. – kkodev Feb 17 '14 at 11:49
-
@KamilKocemba Well done! But if I want change page image segment color how I can do it? I Use `[self.segmentControl insertSegmentWithImage:[[UIImage imageNamed:@"myImage.png"] tintedImageWithColor:[UIColor redColor]] atIndex:i animated:NO];` – user2545330 Mar 31 '14 at 07:24
-
You can also set the titleTextAttributes for just one segmented control by setting segmentedControl setTitleTextAttributes... – jmurphy Apr 18 '14 at 15:28
-
I don't like category approach there is better way to enforce drawing icons in original appearance. See [my answer](http://stackoverflow.com/a/23359699/1387438). – Marek R Apr 29 '14 at 08:50
-
the original question was about changing *only* the border color. this answer changes the text color which affects other portions of the control – Jimmy_m Aug 25 '14 at 13:02
I prefer different solution (no category), when you set images for UISegmentedControl
than you have to alter images like that:
NSArray *items = nil;
if (NSFoundationVersionNumber>NSFoundationVersionNumber_iOS_6_1) {
items = @[
[[UIImage imageNamed:@"Images_Icon_Notes.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal],
[[UIImage imageNamed:@"Images_Icon_Keywords.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal],
[[UIImage imageNamed:@"Images_Icon_Actionitems.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal],
[[UIImage imageNamed:@"Images_Icon_Questions.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]
];
} else {
items = @[
[UIImage imageNamed:@"Images_Icon_Notes.png"],
[UIImage imageNamed:@"Images_Icon_Keywords.png"],
[UIImage imageNamed:@"Images_Icon_Actionitems.png"],
[UIImage imageNamed:@"Images_Icon_Questions.png"]
];
}
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:items];
segmentedControl.tintColor = [UIColor greenColor]; // desired color of border
Now tintColor
will have impact only on border not on icons.
if
provides compatibility with older iOS versions.
I must say this imageWithRenderingMode:
is one of the greatest API WTF I've ever seen.

- 32,568
- 6
- 55
- 140
-
-
"change only border color" by `tintColor`. But this has impact on icons by default, and this prevents this problem. I've assumed that this is obvious, apparently I was wrong so I've made an update. Accepted answer solve same problem using category as a workaround. My approach is much better. – Marek R Apr 29 '14 at 11:49
-
Ups now I've noticed that you threats icons differently then I've expected. Still IMO my answer is quite useful. – Marek R Apr 29 '14 at 11:59
What worked for me: is as other answers suggest, change the tintColor of the segmentedControl to clearColor. And manually tint the images to your app tint color.
Remember to use the imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal
on the tinted image
-(UIImage *)tintedImage:(UIImage *)image withColor:(UIColor *)tintColor
{
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rect = (CGRect){ CGPointZero, image.size };
CGContextSetBlendMode(context, kCGBlendModeNormal);
[image drawInRect:rect];
CGContextSetBlendMode(context, kCGBlendModeSourceIn);
[tintColor setFill];
CGContextFillRect(context, rect);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return [newImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}

- 451
- 9
- 17
You can change first the tintColor and after the titleText.
//Changes Tint Color
segmentedControlName.tintColor = [UIColor colorWithRed:0/255 green:0/255 blue:0/255 alpha:1];
//TitleText to BlackColor
[[UISegmentedControl appearance] setTitleTextAttributes:@{ NSForegroundColorAttributeName : [UIColor blackColor] } forState:UIControlStateNormal];

- 4,566
- 1
- 20
- 28
My solution gives the border of the segmented control another color, and keeps the text as the tint color.
In order to only change the border color of your segmented control, put another segmented control on top of your old one. Then disable user interaction for this new one, and I set the image for the selected segment to nil.
UISegmentedControl *segCtrl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Segm 1", @"Segm 2", @"Segm 3", @"Segm 4", nil]];
// The UISegmentedController which you want to change the border color for
[segCtrl setFrame:CGRectMake(5, 5, [UIScreen mainScreen].bounds.size.width - 10, 30)];
[segCtrl setSelectedSegmentIndex:0];
[segCtrl setTintColor:[UIColor redColor]];
UISegmentedControl *bcg = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@" ", @" ", @" ", @" ", nil]];
// The UISegmentedController you put on top of the other one
[bcg setFrame:CGRectMake(5, 5, [UIScreen mainScreen].bounds.size.width - 10, 30)];
[bcg setSelectedSegmentIndex:0];
[bcg setImage:nil forSegmentAtIndex:0]; // Removing highlight color
[bcg setTintColor:[UIColor greenColor]];
[bcg setUserInteractionEnabled:NO];
[[self view] addSubview:segCtrl];
[[self view] addSubview:bcg];
Of course, you have to take care of the framing and coloring to fit your application. Other than that, this code should be good to go.

- 2,515
- 5
- 21
- 26
-
2a) it's wrong, see the other answer which is more plain and simple b) you are taking wild assumption on how the control looks like with fixed calculations. One minor change to iOS and you would have to update your code. c) you don't overlay two controls unless absolutely required. – dwery Nov 25 '13 at 12:16
for (int i=0; i<[mySegmentedControl.subviews count]; i++)
{
if ([[mySegmentedControl.subviews objectAtIndex:i]isSelected] )
{
[[mySegmentedControl.subviews objectAtIndex:i] setBackgroundColor:[UIColor blueColor]];
[[mySegmentedControl.subviews objectAtIndex:i] setTintColor:[UIColor clearColor]];
}
else
{
[[mySegmentedControl.subviews objectAtIndex:i] setBackgroundColor:[UIColor whiteColor]];
[[mySegmentedControl.subviews objectAtIndex:i] setTintColor:[UIColor clearColor]];
}
}

- 863
- 10
- 26