Is there a way to completely remove the line separating the two segments in a UISegmentedControl?
Setting the segmentedControlStyle is not helping.
Is there a way to completely remove the line separating the two segments in a UISegmentedControl?
Setting the segmentedControlStyle is not helping.
If anybody wants this kind of UISegmentedControl View-
EDITED:- Swift 3.0 extensions
extension UISegmentedControl {
func customizeAppearance(for height: Int) {
setTitleTextAttributes([NSFontAttributeName:UIFont(name:"Helvetica Neue", size:13.0)!,NSForegroundColorAttributeName:UIColor.white], for:.normal)
setTitleTextAttributes([NSFontAttributeName:UIFont(name:"Helvetica Neue", size:13.0)!,NSForegroundColorAttributeName:UIColor.white], for:.selected)
setDividerImage(UIImage().colored(with: .clear, size: CGSize(width: 1, height: height)), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
setBackgroundImage(UIImage().colored(with: .clear, size: CGSize(width: 1, height: height)), for: .normal, barMetrics: .default)
setBackgroundImage(UIImage().colored(with: UIColor.init(red: 215/255.0, green: 0.0, blue: 30/255.0, alpha: 1.0), size: CGSize(width: 1, height: height)), for: .selected, barMetrics: .default);
for borderview in subviews {
let upperBorder: CALayer = CALayer()
upperBorder.backgroundColor = UIColor.init(red: 215/255.0, green: 0.0, blue: 30/255.0, alpha: 1.0).cgColor
upperBorder.frame = CGRect(x: 0, y: borderview.frame.size.height-1, width: borderview.frame.size.width, height: 1)
borderview.layer.addSublayer(upperBorder)
}
}
}
extension UIImage {
func colored(with color: UIColor, size: CGSize) -> UIImage {
UIGraphicsBeginImageContext(size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
}
The UIImage extension generates a colored image with desired size.
Forcing the height parameter in customizeAppearance avoid any crash when building the context.
You can make it even more reusable by extracting each customization attribute and put it as function's parameters ;)
Here is sample code, tested over iOS 9 and works fine for me.
Add these lines of code in viewDidLoad-
[yourSegmentControl setTitleTextAttributes:@{ NSFontAttributeName:[UIFont fontWithName:@"Roboto-black" size:13.0],NSForegroundColorAttributeName:[UIColor whiteColor] }forState:UIControlStateSelected];
[yourSegmentControl setTitleTextAttributes:@{ NSFontAttributeName:[UIFont fontWithName:@"Roboto-black" size:13.0],NSForegroundColorAttributeName:[UIColor whiteColor] }forState:UIControlStateNormal];
[yourSegmentControl setDividerImage:[self imageWithColor:[UIColor clearColor]] forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[yourSegmentControl setBackgroundImage:[self imageWithColor:[UIColor clearColor]] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[yourSegmentControl setBackgroundImage:[self imageWithColor:[UIColor colorWithRed:215/255.0 green:0 blue:30/255.0 alpha:1.0]] forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
for (UIView *borderview in yourSegmentControl.subviews) {
CALayer *upperBorder = [CALayer layer];
upperBorder.backgroundColor = [UIColor colorWithRed:215/255.0 green:0 blue:30/255.0 alpha:1.0].CGColor;
upperBorder.frame = CGRectMake(0, borderview.frame.size.height-1, borderview.frame.size.width, 1.0f);
[borderview.layer addSublayer:upperBorder];
}
and
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Here is the Swift extension for achieving same view in Swift-
yourSegmentControl.setTitleTextAttributes([NSFontAttributeName:UIFont(name:"Helvetica Neue", size:13.0)!,NSForegroundColorAttributeName:UIColor.whiteColor()], forState:UIControlState.Normal)
yourSegmentControl.setTitleTextAttributes([NSFontAttributeName:UIFont(name:"Helvetica Neue", size:13.0)!,NSForegroundColorAttributeName:UIColor.whiteColor()], forState:UIControlState.Selected)
yourSegmentControl.setDividerImage(self.imageWithColor(UIColor.clearColor()), forLeftSegmentState: UIControlState.Normal, rightSegmentState: UIControlState.Normal, barMetrics: UIBarMetrics.Default)
yourSegmentControl.setBackgroundImage(self.imageWithColor(UIColor.clearColor()), forState:UIControlState.Normal, barMetrics:UIBarMetrics.Default)
yourSegmentControl.setBackgroundImage(self.imageWithColor(UIColor.init(red: 215/255.0, green: 0.0, blue: 30/255.0, alpha:1.0)), forState:UIControlState.Selected, barMetrics:UIBarMetrics.Default);
for borderview in yourSegmentControl.subviews {
let upperBorder: CALayer = CALayer()
upperBorder.backgroundColor = UIColor.init(red: 215/255.0, green: 0.0, blue: 30/255.0, alpha: 1.0).CGColor
upperBorder.frame = CGRectMake(0, borderview.frame.size.height-1, borderview.frame.size.width, 1.0);
borderview.layer .addSublayer(upperBorder);
}
and
func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRectMake(0.0, 0.0, 1.0, yourSegmentControl.frame.size.height)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image
}
I combined the previous answers into a Swift extension.
I wanted to remove all borders and dividers. This code just uses the normal segment colors, e.g. tint and background for selected / deselected.
Call
segmentedControl.removeBorders()
Here's the extension
extension UISegmentedControl {
func removeBorders() {
setBackgroundImage(imageWithColor(backgroundColor!), forState: .Normal, barMetrics: .Default)
setBackgroundImage(imageWithColor(tintColor!), forState: .Selected, barMetrics: .Default)
setDividerImage(imageWithColor(UIColor.clearColor()), forLeftSegmentState: .Normal, rightSegmentState: .Normal, barMetrics: .Default)
}
// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image
}
}
The following code will do exactly what you want.
UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, self.segControlOut.frame.size.height), NO, 0.0);
UIImage *blank = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.segControlOut setDividerImage:blank
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
You can remove all background, border and separators from a UISegmentedControl by setting a black image. Or you can set custom colours.
The below example removes all borders/seperators, and sets the background to be white with 0.2 alpha, and the selected segment to be white with alpha 1.0
[self.segmentedControl setBackgroundImage:[self imageWithColor:[UIColor colorWithWhite:1.0 alpha:0.2]] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[self.segmentedControl setBackgroundImage:[self imageWithColor:[UIColor colorWithWhite:1.0 alpha:1.0]] forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
I have used segmentcontrol.tintColor = [UIColor clearColor]; with iOS7 and it seems to work.
@naveed's and @Jon Setting's answers saved my day!
But as a bit of a perfectionist, i was frustrated to find out that this code also leaves holes in the outer border of the control:
So I added a few lines of code to get rid of those and make it look neat:
The complete code for this would be
CGFloat h = self.segControlOut.frame.size.height;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, h), NO, 0.0);
// draw the missing dots with the control border color
[self.segControlOut.tintColor set];
UIRectFrame( CGRectMake(0, -1, 1, 2.5) );
UIRectFrame( CGRectMake(0, h-1.5, 1, 2.5) );
UIImage *blank = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.segControlOut setDividerImage:blank
forLeftSegmentState:UIControlStateNormal
rightSegmentState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
No, there is not. You should look into creating the UISegmentedControl functionality manually. Maybe use two UIButtons.
- (void) configSegmentControl {
[segmentControl setBackgroundImage:[self imageWithColor:[UIColor blueColor]] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[segmentControl setBackgroundImage:[self imageWithColor:[UIColor redColor]] forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
segmentControl.layer.cornerRadius = 4.0f;
segmentControl.clipsToBounds = YES;
}
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}