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.
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];
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;
}
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]];
}
}
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.
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.
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];
}