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 cont
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
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)
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!
}
}
mySegmentedControl.removeBorders()
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
}
}
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.
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()