How to Remove Border from Segmented Control

How to remove border from segmented control

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.

UISegmentedControl Borders/Highlighted State

This is how you can change the background color for selected indicator in UISegmentControl

extension UISegmentedControl{
func removeBorders() {
setBackgroundImage(imageWithColor(color: .clear), for: .normal, barMetrics: .default)
setBackgroundImage(imageWithColor(color: .gray), 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!
}
}

As you can see in removeBorders function you are setting background image based on color for normal and selected state. So here you can use whatever color you like.

Remove UISegmentedControl separators completely. (iphone)

No, there is not. You should look into creating the UISegmentedControl functionality manually. Maybe use two UIButtons.

How to display only bottom border for selected item in UISegmentedControl?

Add the following code in a separate swift file (command+N -> New File):

extension UISegmentedControl{
func removeBorder(){
let backgroundImage = UIImage.getColoredRectImageWith(color: UIColor.white.cgColor, andSize: self.bounds.size)
self.setBackgroundImage(backgroundImage, for: .normal, barMetrics: .default)
self.setBackgroundImage(backgroundImage, for: .selected, barMetrics: .default)
self.setBackgroundImage(backgroundImage, for: .highlighted, barMetrics: .default)

let deviderImage = UIImage.getColoredRectImageWith(color: UIColor.white.cgColor, andSize: CGSize(width: 1.0, height: self.bounds.size.height))
self.setDividerImage(deviderImage, forLeftSegmentState: .selected, rightSegmentState: .normal, barMetrics: .default)
self.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.gray], for: .normal)
self.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor(red: 67/255, green: 129/255, blue: 244/255, alpha: 1.0)], for: .selected)
}

func addUnderlineForSelectedSegment(){
removeBorder()
let underlineWidth: CGFloat = self.bounds.size.width / CGFloat(self.numberOfSegments)
let underlineHeight: CGFloat = 2.0
let underlineXPosition = CGFloat(selectedSegmentIndex * Int(underlineWidth))
let underLineYPosition = self.bounds.size.height - 1.0
let underlineFrame = CGRect(x: underlineXPosition, y: underLineYPosition, width: underlineWidth, height: underlineHeight)
let underline = UIView(frame: underlineFrame)
underline.backgroundColor = UIColor(red: 67/255, green: 129/255, blue: 244/255, alpha: 1.0)
underline.tag = 1
self.addSubview(underline)
}

func changeUnderlinePosition(){
guard let underline = self.viewWithTag(1) else {return}
let underlineFinalXPosition = (self.bounds.width / CGFloat(self.numberOfSegments)) * CGFloat(selectedSegmentIndex)
UIView.animate(withDuration: 0.1, animations: {
underline.frame.origin.x = underlineFinalXPosition
})
}
}

extension UIImage{

class func getColoredRectImageWith(color: CGColor, andSize size: CGSize) -> UIImage{
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
let graphicsContext = UIGraphicsGetCurrentContext()
graphicsContext?.setFillColor(color)
let rectangle = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
graphicsContext?.fill(rectangle)
let rectangleImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return rectangleImage!
}
}

Then after call segmentedControl.addUnderlineForSelectedSegment() from your viewDidLoad() method, and create an @IBAction method for the segmented control like so:

@IBAction func segmentedControlDidChange(_ sender: UISegmentedControl){
segmentedControl.changeUnderlinePosition()
}

Then call segmentedControl.changeUnderlinePosition() from within this method.

Do not forget to connect the segmented control from your storyboard to the @IBAction method you just created.

Very important: Don't forget to use Auto layout in the storyboard to determine the size and position of your segmented control.

This is the result:

enter image description here

enter image description here

enter image description here

Feel free to ask any other questions you may have :)

How to set borderColor of `UISegmentControl` in `swift`?

You literally just have to convert the code to swift...

let customSegmentedControl = UISegmentedControl.appearance()    
customSegmentedControl.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.red], for: UIControlState.normal)

But I believe the code you posted changes the actual color of the letters, not the color outside. The color outside is called "tint" and it's changed like this:

customSegmentedControl.tintColor = UIColor.blue

EDIT: For ONLY changing the border

Since each segment in the SegmentedControl is an actual UIView you can access them directly and customize them per your needs as in this answer.

Or you can set the "background image" which I believe can be set to the color you need. (Although the method above seems less complicated)

How to customize UISegmentedControl to change selected segment bottom border?

Use extension with this
self.segmentController.customizeAppearance(for: 1)

Call addBorder method and pass your UISegmentedControl as a parameter

    static func addBorder(_ uiSegmentControl: UISegmentedControl){

var upperBorder: CALayer = CALayer()
upperBorder.backgroundColor = UIColor.init(red: 255.0, green:255.0, blue: 255.0, alpha: 1.0).cgColor
upperBorder.frame = CGRect(x: 0, y: Int(ceil(uiSegmentControl.subviews[0].bounds.height))-1, width: Int(floor(uiSegmentControl.bounds.width)), height: 1)
uiSegmentControl.layer.addSublayer(upperBorder)

for i in 0..<uiSegmentControl.subviews.count {

if i == uiSegmentControl.selectedSegmentIndex {
upperBorder = CALayer()
upperBorder.backgroundColor = UIColor.init(red: 215/255.0, green: 0.0, blue: 30/255.0, alpha: 1.0).cgColor
upperBorder.frame = CGRect(x: i*Int(ceil(uiSegmentControl.subviews[i].bounds.width)), y: Int(ceil(uiSegmentControl.subviews[i].bounds.height))-1, width: Int(floor(uiSegmentControl.subviews[i].bounds.width)), height: 1)
uiSegmentControl.layer.addSublayer(upperBorder)
}
}

}

extension UISegmentedControl {
func customizeAppearance(for height: Int) {
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)
}
}
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!
}


Related Topics



Leave a reply



Submit