How to change the corner radius of UISegmentedControl?

IosCocoa TouchUiviewUikitUisegmentedcontrol

Ios Problem Overview


Is it possible to change the corner radius of UISegmentedControl? I have tried the following approach which we use to change a UIView's corner radius.

self.segmentedControl.layer.cornerRadius = 15.0;
self.segmentedControl.layer.masksToBounds = YES;

This did not work as you can see it only cuts off the UISegmentedControl's corner:

cut off corner

Ios Solutions


Solution 1 - Ios

This should work:

self.segmentedControl.layer.cornerRadius = 15.0;
self.segmentedControl.layer.borderColor = [UIColor whiteColor].CGColor;
self.segmentedControl.layer.borderWidth = 1.0f;
self.segmentedControl.layer.masksToBounds = YES;

You need to specify the border after setting cornerRadius.

Solution 2 - Ios

Embed UISegmentedControl inside UIView and set corner radius for UIView.

Objective-C

outerView.layer.cornerRadius = CGRectGetHeight(outerView.bounds) / 2;
outerView.layer.borderColor = [UIColor blueColor].CGColor;
outerView.layer.borderWidth = 1;

Swift

outerView.layer.cornerRadius = CGRectGetHeight(outerView.bounds) / 2
outerView.layer.borderColor = UIColor.blueColor().CGColor
outerView.layer.borderWidth = 1

Cornered UISegmentedControl

Solution 3 - Ios

iOS 13 / 14 - FINALLY WORKING!!!

image alt

I decided to give it another go, and I finally got it working perfectly!! There's one line of code that fixed it all! Check out the code

Code:

class CustomSegmentedControl: UISegmentedControl{
    private let segmentInset: CGFloat = 5       //your inset amount
    private let segmentImage: UIImage? = UIImage(color: UIColor.red)    //your color

    override func layoutSubviews(){
        super.layoutSubviews()

        //background
        layer.cornerRadius = bounds.height/2
        //foreground
        let foregroundIndex = numberOfSegments
        if subviews.indices.contains(foregroundIndex), let foregroundImageView = subviews[foregroundIndex] as? UIImageView
        {
            foregroundImageView.bounds = foregroundImageView.bounds.insetBy(dx: segmentInset, dy: segmentInset)
            foregroundImageView.image = segmentImage    //substitute with our own colored image
            foregroundImageView.layer.removeAnimation(forKey: "SelectionBounds")    //this removes the weird scaling animation!
            foregroundImageView.layer.masksToBounds = true
            foregroundImageView.layer.cornerRadius = foregroundImageView.bounds.height/2
        }
    }
}

extension UIImage{
    
    //creates a UIImage given a UIColor
    public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
        let rect = CGRect(origin: .zero, size: size)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
        color.setFill()
        UIRectFill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    
        guard let cgImage = image?.cgImage else { return nil }
        self.init(cgImage: cgImage)
    }
}

The idea is that Apple uses a UIImageView with its own square image and tint for the selected moving segment. What we want to do is instead overwrite its image so we have control on the color, corner radius, etc. After that, we want to remove one of Apple's 3 default animations (the one that was problematic made the segment scale up on touch -- I used foregroundImageView.layer.animationKeys() to find out what animations were affecting the moving segment)

Solution 4 - Ios

The segmented control is not going to change the way it draws its corners, so it is continuing to draw its corners in its own way and you are then cutting them off. You are not in charge of how a segmented control draws its boundary shape. If you truly don't like the way it's drawn, you'll have to devise your own substitute control from scratch. The closest you can legitimately come to the kind of thing you're trying to do is to set the segmented control's background image.

Solution 5 - Ios

You're able to change the UISegmentedControl cornerRadius by increasing the layer its cornerRadius or from iOS 13 and above by setting the layer its maskedCorner property.

This example removes the default cornerRadius and straightens the backgroundImage:

if #available(iOS 13.0, *) {
    segmentedControl.layer.maskedCorners = .init()
} else {
    segmentedControl.layer.cornerRadius = 0
}

Source: https://developer.apple.com/documentation/quartzcore/calayer/2877488-maskedcorners

Solution 6 - Ios

Updated for Swift 3 & Xcode 8.2 compatibility

mySegmentedControl.layer.cornerRadius = 25.0
mySegmentedControl.layer.borderColor = UIColor.white.cgColor
mySegmentedControl.layer.borderWidth = 1.0
mySegmentedControl.layer.masksToBounds = true

Solution 7 - Ios

There are some changes in iOS13. Hence you must set the borderRadius from within layoutSubviews:

override func layoutSubviews() {
    super.layoutSubviews()
    layer.cornerRadius = 2
}

Solution 8 - Ios

The previous solutions never worked for me. My solution is:

To embed the UISegmentedControl inside a superview, then assign -1 to the constraints leading, trailing, bottom, top, in order to cut off the UISegmentedControl border. Finally the superview should be configured in this way:

segmentedControl.superview.clipsToBounds = true
segmentedControl.superview.layer.cornerRadius = 0 //whatever
segmentedControl.superview.layer.borderWidth = 1
segmentedControl.superview.layer.borderColor = segmentedControl.tintColor.CGColor

Solution 9 - Ios

Your result is because something other (custom drawing?) controls the border and not the layer. Luckily it seems that that layer settings have priority.

If you know what border color you need, you can just add (example):

self.segmentedControl.layer.borderColor = [UIColor whiteColor].CGColor;
self.segmentedControl.layer.borderWidth = 1.0;

Solution 10 - Ios

This is a converted and working code for Swift 4.1 and Xcode 9.3 of Yakiv's post.

segmentedOuterView.layer.cornerRadius = segmentedOuterView.bounds.height / 2
segmentedOuterView.layer.borderColor = UIColor.red.cgColor
segmentedOuterView.layer.borderWidth = 1
segmentedOuterView.layer.masksToBounds = true

Solution 11 - Ios

Use the following code :

segmentContrl.layer.borderColor=*anycolor*.CGColor;
segmentContrl.layer.cornerRadius = 0.0;
segmentContrl.layer.borderWidth = 1.5f;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionwz366View Question on Stackoverflow
Solution 1 - Iosxi.linView Answer on Stackoverflow
Solution 2 - IosYakiv KovalskyiView Answer on Stackoverflow
Solution 3 - IosMerricatView Answer on Stackoverflow
Solution 4 - IosmattView Answer on Stackoverflow
Solution 5 - IosLloyd KeijzerView Answer on Stackoverflow
Solution 6 - IosdeijmasterView Answer on Stackoverflow
Solution 7 - IosmfaaniView Answer on Stackoverflow
Solution 8 - IosAndrea MugnainiView Answer on Stackoverflow
Solution 9 - IosMihai TimarView Answer on Stackoverflow
Solution 10 - IosatereshkovView Answer on Stackoverflow
Solution 11 - Iosswathy krishnanView Answer on Stackoverflow