How do I remove the outside border of a segmented control? I've set the divider image to what I wanted but now to follow the mock of my app I need to have a segmented control without the outer border.
9 Answers
What you must understand is the backgroundColor
property is not stateful.
Hence you have to use setBackgroundImage(_:for:barMetrics:)
.
We can easily remove both borders and dividers using the below function.
For Swift 3 & 4+:
extension UISegmentedControl {
func removeBorders() {
setBackgroundImage(imageWithColor(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
}
// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
}
For Swift 2.2:
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
}
}
Call the above function.
segmentedControl.removeBorders()
Reference: Remove UISegmentedControl separators completely. (iphone)
Thanks to https://stackoverflow.com/users/3921490/amagain for Swift 3 version.

- 9,404
- 1
- 31
- 57
-
Thanks :) It worked =D But one more question, this will make my segmented control have a sharp rectangular corner, any ways to make it rounded? – Happiehappie Jul 28 '15 at 03:33
-
@Happiehappie no you can't, please refer to this answer http://stackoverflow.com/questions/1834244/uisegmentedcontrol-without-rounded-corner – Sohil R. Memon Jul 28 '15 at 06:51
-
I am getting `fatal error: unexpectedly found nil while unwrapping an Optional value` on line `setBackgroundImage(imageWithColor(color: backgroundColor!), for: .normal, barMetrics: .default)` – Kakaji May 30 '17 at 09:33
-
You also need to set background color to some color other that `Default` apparently. `backgroundColor` was nil when it was set to `Default`. – Kakaji May 30 '17 at 09:39
-
3To fix the background nil issue: `setBackgroundImage(imageWithColor(color: backgroundColor ?? .white), for: .normal, barMetrics: .default)` – Whoa Oct 18 '17 at 13:48
-
Doesn't work anymore on iOS13! Have a look at this question - https://stackoverflow.com/questions/57450865/uisegmentedcontrol-ios-13-clear-color – Deepak Sharma Aug 11 '19 at 14:46
Here's the swift 3 version of Sohil's answer that might help someone else. It did help me. :)
extension UISegmentedControl {
func removeBorders() {
setBackgroundImage(imageWithColor(color: backgroundColor!), for: .normal, barMetrics: .default)
setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
}
// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
}
Hope it will help someone
Swift - 4
Make the Background color and Tint color of your Segment control to same color. Then "set titleTextAttributes" of your Segment control
segmentedControl.tintColor = UIColor.red
segmentedControl.backgroundColor = UIColor.red
let attributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
segmentedControl.setTitleTextAttributes(attributes, for: .normal)
segmentedControl.setTitleTextAttributes(attributes, for: .selected)

- 884
- 1
- 15
- 22
-
1
-
Yea correct. This is trick when the backgroundColor and Tint color is same then the borderColor will be same color as TintColor. – kalpa Apr 02 '19 at 09:10
If you want save borders between cells
extension UISegmentedControl {
func removeBorders() {
if let backgroundColor = backgroundColor, let backgroundImage = UIImage.imageWithSize(size: CGSize.one_one, color: backgroundColor){
setBackgroundImage(backgroundImage, for: .normal, barMetrics: .default)
}
if let tintColor = tintColor, let tintImage = UIImage.imageWithSize(size: CGSize.one_one, color: tintColor){
setBackgroundImage(tintImage, for: .selected, barMetrics: .default)
setDividerImage(tintImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
}
}
}
extension CGSize{
static var one_one: CGSize{
return CGSize(width: 1.0, height: 1.0)
}
}
extension UIImage{
static func imageWithSize(size : CGSize, color : UIColor = UIColor.white) -> UIImage? {
var image:UIImage? = nil
UIGraphicsBeginImageContext(size)
if let context = UIGraphicsGetCurrentContext() {
context.setFillColor(color.cgColor)
context.addRect(CGRect(origin: CGPoint.zero, size: size));
context.drawPath(using: .fill)
image = UIGraphicsGetImageFromCurrentImageContext();
}
UIGraphicsEndImageContext()
return image
}
}

- 2,747
- 10
- 38
- 53

- 363
- 3
- 9
You might have the usecase where you don't want the rounded border as you don't want to see it if it's embedded in a cell. In this case, set the autolayout constraints to -2 and the border will be hidden as it will extend beyond the cell border.

- 336
- 8
- 21
- 41
If you need segment control with texts Only, use,
segmentControl.backgroundColor = .clear
segmentControl.tintColor = .clear
let attributes: [NSAttributedString.Key : Any] = [.font : UIFont(family: .medium, ofSize: 13)!, .foregroundColor : UIColor.white]
segmentControl.setTitleTextAttributes(attributes, for: .normal)
let selectedAttrib: [NSAttributedString.Key : Any] = [.font : UIFont(family: .medium, ofSize: 13)!, .foregroundColor : UIColor.red]
segmentControl.setTitleTextAttributes(hightLightedStateAttrib, for: .selected)
NB: I googled it for a long time, thats why i'm posted here.
Source: CodeMentor

- 15,485
- 6
- 64
- 84
- The accepted answer works for getting rid of the border.
- The solution mentioned here also works for disabling the segmented Control.
Yet putting the two solutions together, I wasn't able to get the correct selected segment in a disabled
state.
What I wanted was that upon selecting a segment and making a network call, I wanted to disable the segmented control.
The outcome was like this:
What was desired was this:
The only addition to Sohil's solution is:
setBackgroundImage(imageWithColor(color: imageWithColor(color: tintColor)), for: [.selected, .disabled], barMetrics: .default)
After the selected && disabled segment will have the right color.

- 33,269
- 19
- 164
- 293
Swift 5.x:
This solution remove only the external border and preserve the round corner on each button
extension UISegmentedControl {
func removeBorders(andBackground:Bool=false) {
setBackgroundImage(imageWithColor(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
_ = self.subviews.compactMap {
if ($0.frame.width>0) {
$0.layer.cornerRadius = 8
$0.layer.borderColor = UIColor.clear.cgColor
$0.clipsToBounds = true
$0.layer.borderWidth = andBackground ? 1.0 : 0.0
$0.layer.borderColor = andBackground ? tintColor?.cgColor : UIColor.clear.cgColor
andBackground ? $0.layer.backgroundColor = UIColor.clear.cgColor : nil
}
}
}
// create a 1x1 image with this color
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor);
context!.fill(rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image!
}
}
Usage:
mySegmentedControl.removeBorders()

- 34,887
- 11
- 106
- 133
-
-
@RoneySampaio The purpose of this method was to remove the external round corners, have you read the title and the description? It re-create the round corner to each button inside.. – Alessandro Ornano Nov 01 '19 at 12:40
Sohil's answer did help me.
But if you don't set the UIImage
size, it may affect the size of the UISegmentedControl
.
If you also encounter this problem, please consider using the following code.
func *(lhs: CGSize, rhs: CGFloat) -> CGSize {
return CGSize(width: lhs.width * rhs, height: lhs.height * rhs)
}
extension UIImage {
func resized(_ size: CGSize) -> UIImage? {
defer { UIGraphicsEndImageContext() }
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
self.draw(in: CGRect(origin: .zero, size: size))
return UIGraphicsGetImageFromCurrentImageContext()
}
func resized(_ size: CGFloat) -> UIImage? {
guard size > 0, self.size.width > 0, self.size.height > 0 else { return nil }
let ratio = size / max(self.size.width, self.size.height)
return self.resized(self.size * ratio)
}
func refilled(_ color: UIColor) -> UIImage? {
defer { UIGraphicsEndImageContext() }
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
color.set()
UIGraphicsGetCurrentContext()?.fill(CGRect(origin: .zero, size: self.size))
return UIGraphicsGetImageFromCurrentImageContext()
}
public convenience init?(color: UIColor = .clear, size: CGSize) {
defer { UIGraphicsEndImageContext() }
UIGraphicsBeginImageContext(size)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
context.setFillColor(color.cgColor);
context.fill(CGRect(origin: .zero, size: size));
guard let cgImage = UIGraphicsGetImageFromCurrentImageContext()?.cgImage else { return nil }
self.init(cgImage: cgImage)
}
}
extension UISegmentedControl {
func removeBorders() {
let image = UIImage(size: self.bounds.size)
self.setBackgroundImage(image, for: .normal, barMetrics: .default)
self.setBackgroundImage(image?.refilled(self.tintColor), for: .selected, barMetrics: .default)
self.setDividerImage(image?.resized(1), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
}
}
Easy to use:
segmentedControl.removeBorders()

- 6,562
- 1
- 36
- 30