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

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 :)


A.Jam's answer in Xcode 9.3, Swift 4.2 version

import UIKitextension 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([NSAttributedStringKey.foregroundColor: UIColor.gray], for: .normal)        self.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: 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!    }}


you can use this

let segmentBottomBorder = CALayer()segmentBottomBorder?.borderColor = UIColor.blue.cgColorsegmentBottomBorder?.borderWidth = 3let x = CGFloat(sender.selectedSegmentIndex) * widthlet y = sender.frame.size.height - (segmentBottomBorder?.borderWidth)!let width: CGFloat = sender.frame.size.width/3segmentBottomBorder?.frame = CGRect(x: x, y: y, width: width, height: (segmentBottomBorder?.borderWidth)!)sender.layer.addSublayer(segmentBottomBorder!)