Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the corner radius of UISegmentedControl?

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

like image 397
wz366 Avatar asked Apr 26 '14 23:04

wz366


People also ask

How do you change the corner radius of a storyboard?

Select the view that you want to round and open its Identity Inspector. In the User Defined Runtime Attributes section, add the following two entries: Key Path: layer. cornerRadius , Type: Number, Value: (whatever radius you want)

How do you round the corners of a view?

You can give it round corners by changing the cornerRadius property of the view's layer . and smaller values give less rounded corners. Both clipsToBounds and masksToBounds are equivalent. It is just that the first is used with UIView and the second is used with CALayer .


4 Answers

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.

like image 81
xi.lin Avatar answered Oct 01 '22 23:10

xi.lin


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

like image 27
Yakiv Kovalskyi Avatar answered Oct 01 '22 23:10

Yakiv Kovalskyi


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)

like image 28
Merricat Avatar answered Oct 01 '22 21:10

Merricat


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.

like image 20
matt Avatar answered Oct 01 '22 23:10

matt