How to set layer cornerRadius for only bottom-left, bottom-right, and top-left corner?
Asked Answered
T

13

92

How to set corner radius only only bottom-left, bottom-right, and top-left corners of a textview?

let rectShape = CAShapeLayer()
rectShape.backgroundColor = UIColor.redColor().CGColor
rectShape.bounds = messages.frame
rectShape.position = messages.center
rectShape.path = UIBezierPath(roundedRect: messages.bounds, byRoundingCorners: .BottomLeft | .TopRight, cornerRadii: CGSize(width: 20, height: 20)).CGPath

messages.layer.addSublayer(rectShape)

this code creates two rects. I dont know why.

Twinge answered 5/7, 2015 at 16:45 Comment(3)
In this code instead of adding mask you are adding rectshape as sublayer of your messages textViewAlibi
Zept, Does it make sense???Alibi
#31233189Superabundant
A
82

You just need to mask the layer as shown below:

For Swift 3:

let rectShape = CAShapeLayer()
rectShape.bounds = self.myView.frame
rectShape.position = self.myView.center
rectShape.path = UIBezierPath(roundedRect: self.myView.bounds, byRoundingCorners: [.bottomLeft , .bottomRight , .topLeft], cornerRadii: CGSize(width: 20, height: 20)).cgPath

self.myView.layer.backgroundColor = UIColor.green.cgColor
//Here I'm masking the textView's layer with rectShape layer
self.myView.layer.mask = rectShape

Lower Version:

let rectShape = CAShapeLayer()
rectShape.bounds = self.myView.frame
rectShape.position = self.myView.center
rectShape.path = UIBezierPath(roundedRect: self.myView.bounds, byRoundingCorners: .BottomLeft | .BottomRight | .TopLeft, cornerRadii: CGSize(width: 20, height: 20)).CGPath

self.myView.layer.backgroundColor = UIColor.greenColor().CGColor
//Here I'm masking the textView's layer with rectShape layer
self.myView.layer.mask = rectShape
Alibi answered 5/7, 2015 at 17:40 Comment(11)
Sorry, I would like to ask another question. I can not rounded the corner to the right. .TopRight And .ButtonRight not workTwinge
Just add this code to new controller and check it once because it might be a problem with your auto layout..for me it works properlyAlibi
Output will look something like this dropbox.com/s/cfjp27xnpeetonp/…Alibi
I think byRoundingCorners takes an array, so in the above example it should be: byRoundingCorners: [.BottomLeft, .BottomRight, .TopLeft]Shortcake
Its possible to delete them: rectShape.position = self.myView.center ??Luckett
not working for bottom. i.e. bottomLeft & bottomRightHumdrum
Is it Possible to give shadow for a view along with corner radius on one edge??Cardoza
leaving space on right side after textfield corner radius topleft and bottomleft in iPhone8PlusNeedlecraft
Can we add bottom shadow along with corners: [.BottomLeft, .BottomRight]Wolcott
this makes my view disapper!Deneb
For those who this answer didn't work, please add your code in viewDidLayoutSubviews()Forsooth
S
221

(swift 4/iOS 11) Just simply say for bottom:

yourView.clipsToBounds = true 
yourView.layer.cornerRadius = 10
yourView.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]

for Up:

yourView.clipsToBounds = true 
yourView.layer.cornerRadius = 10
yourView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]

in your case:

yourView.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner]

Hope this help :)

Sheugh answered 25/9, 2017 at 15:19 Comment(1)
CACornerMask extension constants so humans can understand: gist.github.com/derekleerock/19a767c528b53ffa381a51c49f220595Carboy
A
82

You just need to mask the layer as shown below:

For Swift 3:

let rectShape = CAShapeLayer()
rectShape.bounds = self.myView.frame
rectShape.position = self.myView.center
rectShape.path = UIBezierPath(roundedRect: self.myView.bounds, byRoundingCorners: [.bottomLeft , .bottomRight , .topLeft], cornerRadii: CGSize(width: 20, height: 20)).cgPath

self.myView.layer.backgroundColor = UIColor.green.cgColor
//Here I'm masking the textView's layer with rectShape layer
self.myView.layer.mask = rectShape

Lower Version:

let rectShape = CAShapeLayer()
rectShape.bounds = self.myView.frame
rectShape.position = self.myView.center
rectShape.path = UIBezierPath(roundedRect: self.myView.bounds, byRoundingCorners: .BottomLeft | .BottomRight | .TopLeft, cornerRadii: CGSize(width: 20, height: 20)).CGPath

self.myView.layer.backgroundColor = UIColor.greenColor().CGColor
//Here I'm masking the textView's layer with rectShape layer
self.myView.layer.mask = rectShape
Alibi answered 5/7, 2015 at 17:40 Comment(11)
Sorry, I would like to ask another question. I can not rounded the corner to the right. .TopRight And .ButtonRight not workTwinge
Just add this code to new controller and check it once because it might be a problem with your auto layout..for me it works properlyAlibi
Output will look something like this dropbox.com/s/cfjp27xnpeetonp/…Alibi
I think byRoundingCorners takes an array, so in the above example it should be: byRoundingCorners: [.BottomLeft, .BottomRight, .TopLeft]Shortcake
Its possible to delete them: rectShape.position = self.myView.center ??Luckett
not working for bottom. i.e. bottomLeft & bottomRightHumdrum
Is it Possible to give shadow for a view along with corner radius on one edge??Cardoza
leaving space on right side after textfield corner radius topleft and bottomleft in iPhone8PlusNeedlecraft
Can we add bottom shadow along with corners: [.BottomLeft, .BottomRight]Wolcott
this makes my view disapper!Deneb
For those who this answer didn't work, please add your code in viewDidLayoutSubviews()Forsooth
B
65

Swift 3

extension UIView {
    func roundCorners(_ corners:UIRectCorner, radius: CGFloat) {
    let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.cgPath
    self.layer.mask = mask
  }
}

Use like this

YourView.roundCorners([.topLeft, .bottomLeft], radius: 10)
Boote answered 19/12, 2016 at 7:34 Comment(9)
not working for bottom. i.e. bottomLeft & bottomRightHumdrum
Works beautifully, for all corners. Thanks!Agronomics
@Agronomics Glad to help youBoote
I have a problem with TopRight and bottom right. :(Derision
I faced similar issue of not working for top right and bottom right. I fixed it by calling it in viewDidLayoutSubviews for view controller and layoutSubviews for tableview cells. It worked for me.Israel
@MuseerAhamadAnsari Does it work on iPhone XR? In my case it's not working.Problem
How can I add shadow to view with rounded corner in top left and top right ?Galla
try what @Israel suggested, for me it's working now, thanksUzziel
For those who this answer didn't work, please add "YourView.roundCorners([.topLeft, .bottomLeft], radius: 10)" this in viewDidLayoutSubviews()Forsooth
S
29

A better answer for both iOS 11 and iOS 10 bottom corner would be

 if #available(iOS 11.0, *){
        view.clipsToBounds = true
        view.layer.cornerRadius = 10
        view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
    }else{
       let rectShape = CAShapeLayer()
       rectShape.bounds = view.frame
       rectShape.position = view.center
       rectShape.path = UIBezierPath(roundedRect: view.bounds,    byRoundingCorners: [.bottomLeft , .bottomRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
      view.layer.backgroundColor = UIColor.green.cgColor
      view.layer.mask = rectShape
  }

in case this didnt work on iOS 10 and below, try running the code in viewDidLayoutSubviews() of your viewcontroller class like this

override func viewDidLayoutSubviews() {
    if #available(iOS 11.0, *){
    }else{
       let rectShape = CAShapeLayer()
       rectShape.bounds = view.frame
       rectShape.position = view.center
       rectShape.path = UIBezierPath(roundedRect: view.bounds,    byRoundingCorners: [.bottomLeft , .bottomRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
       view.layer.backgroundColor = UIColor.green.cgColor
       view.layer.mask = rectShape
}
Sampling answered 17/4, 2018 at 19:56 Comment(2)
Works perfectly fine for iOS 11Carniola
works perfectly for ios 10. it was not working for the top & right corners but moving the code to viewDidLayoutSubViews solved the problem. ThanksCustody
E
28

Swift 4+

func roundCorners(with CACornerMask: CACornerMask, radius: CGFloat) {
    self.layer.cornerRadius = radius
    self.layer.maskedCorners = [CACornerMask]
}

How to use

//Top right
roundCorners(with: [.layerMaxXMinYCorner], radius: 20)

//Top left
roundCorners(with: [.layerMinXMinYCorner], radius: 20)

//Bottom right
roundCorners(with: [.layerMaxXMaxYCorner], radius: 20)

//Bottom left 
roundCorners(with: [.layerMinXMaxYCorner], radius: 20)

OR

Another way using CACornerMask

extension UIView{
    
    enum RoundCornersAt{
        case topRight
        case topLeft
        case bottomRight
        case bottomLeft
    }
    
        //multiple corners using CACornerMask
    func roundCorners(corners:[RoundCornersAt], radius: CGFloat) {
        self.layer.cornerRadius = radius
        self.layer.maskedCorners = [
            corners.contains(.topRight) ? .layerMaxXMinYCorner:.init(),
            corners.contains(.topLeft) ? .layerMinXMinYCorner:.init(),
            corners.contains(.bottomRight) ? .layerMaxXMaxYCorner:.init(),
            corners.contains(.bottomLeft) ? .layerMinXMaxYCorner:.init(),
        ]
    }
    
}

You can use like below

myView.roundCorners(corners: [.topLeft,.bottomLeft], radius: 20)

OR

Multiple corners using UIRectCorner

func roundedCorners(corners : UIRectCorner, radius : CGFloat) {
    let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.cgPath
    layer.mask = mask
}

How to use

roundedCorners(corners: [.topLeft, .topRight], radius: 20)
Ermine answered 12/11, 2019 at 9:19 Comment(1)
This is the best answer i found. ThanksSevastopol
A
11

For subview & POPUPs [Swift 5]

override func layoutSublayers(of layer: CALayer) {
    searchBarPopup.clipsToBounds = true
    searchBarPopup.layer.cornerRadius = 10
    searchBarPopup.layer.maskedCorners = [ .layerMaxXMinYCorner, .layerMinXMinYCorner]
}

output:

enter image description here

Auricular answered 22/10, 2019 at 8:23 Comment(1)
please add some explaination it will help new people to understand what u writeBarrelchested
E
10

Swift 4

override func viewDidLoad() {
    let topRight = UIView(frame: CGRect(x: 120, y: 200, width: 120, height: 120))
    topRight.roundedTop()
    topRight.backgroundColor = .red
    self.view.center = topRight.center
    self.view.addSubview(topRight)
    super.viewDidLoad()
}

Output :

enter image description here

extension on UIView Swift 4 : Reference Link

Epps answered 6/6, 2018 at 3:12 Comment(0)
M
9

Here is an extension for iOS 11+

 import Foundation
 import UIKit

 extension UIView {

   func roundCorners(_ corners: CACornerMask, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
       self.layer.maskedCorners = corners
       self.layer.cornerRadius = radius
       self.layer.borderWidth = borderWidth
       self.layer.borderColor = borderColor.cgColor
    
   }

 }

Usage:-

self.yourView.roundCorners([.layerMaxXMaxYCorner, .layerMaxXMinYCorner], radius: 20.0, borderColor: UIColor.green, borderWidth: 1)

Swift 5+

view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner]
Mandamandaean answered 24/8, 2018 at 4:20 Comment(0)
U
9
  1. Add RoundedCornerView.swift file to your project
  2. Add an UIView to your ViewController
  3. Change Custom Class in Identity Inspector to RoundedCornerView
  4. Go to Attribute Inspector pick Corner Radius (CGFloat) and On the corners you want rounded.

rounded corner view

RoundedCornerView.swift

import UIKit

@IBDesignable
class RoundedCornerView: UIView {

    var cornerRadiusValue : CGFloat = 0
    var corners : UIRectCorner = []

    @IBInspectable public var cornerRadius : CGFloat {
        get {
            return cornerRadiusValue
        }
        set {
            cornerRadiusValue = newValue
        }
    }

    @IBInspectable public var topLeft : Bool {
        get {
            return corners.contains(.topLeft)
        }
        set {
            setCorner(newValue: newValue, for: .topLeft)
        }
    }

    @IBInspectable public var topRight : Bool {
        get {
            return corners.contains(.topRight)
        }
        set {
            setCorner(newValue: newValue, for: .topRight)
        }
    }

    @IBInspectable public var bottomLeft : Bool {
        get {
            return corners.contains(.bottomLeft)
        }
        set {
            setCorner(newValue: newValue, for: .bottomLeft)
        }
    }

    @IBInspectable public var bottomRight : Bool {
        get {
            return corners.contains(.bottomRight)
        }
        set {
            setCorner(newValue: newValue, for: .bottomRight)
        }
    }

    func setCorner(newValue: Bool, for corner: UIRectCorner) {
        if newValue {
            addRectCorner(corner: corner)
        } else {
            removeRectCorner(corner: corner)
        }
    }

    func addRectCorner(corner: UIRectCorner) {
        corners.insert(corner)
        updateCorners()
    }

    func removeRectCorner(corner: UIRectCorner) {
        if corners.contains(corner) {
            corners.remove(corner)
            updateCorners()
        }
    }

    func updateCorners() {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: cornerRadiusValue, height: cornerRadiusValue))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }

}

github link : RoundedCornerView

Ulphia answered 13/4, 2019 at 16:12 Comment(3)
Thanks the library it worked, but it will not update very quick in storyboard, we need off and on the properties then only it will updateSevastopol
it's ok in storyboard but only works for left corners on devie. why?Mussulman
@MahdiMoqadasi if your device width is not same as simulator device then it might not show up on actual device. Better solution is set all corners you want rounded set true in viewDidLayoutSubviews() function. For example inside viewDidLayoutSubviews() function write: roundedView.topLeft = true roundedView.topRight = true it will redraw according to width of your view. Hope it helps.Ulphia
F
5

The best solution I could come up with all of the above solution is this.

extension UIView {
    func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
        if #available(iOS 11, *) {
            var cornerMask = CACornerMask()
            if(corners.contains(.topLeft)){
                cornerMask.insert(.layerMinXMinYCorner)
            }
            if(corners.contains(.topRight)){
                cornerMask.insert(.layerMaxXMinYCorner)
            }
            if(corners.contains(.bottomLeft)){
                cornerMask.insert(.layerMinXMaxYCorner)
            }
            if(corners.contains(.bottomRight)){
                cornerMask.insert(.layerMaxXMaxYCorner)
            }
            self.layer.cornerRadius = radius
            self.layer.maskedCorners = cornerMask

        } else {
            let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            self.layer.mask = mask
        }
    }
}

I believe that this way the implementation is easy while selecting the sides.

view.roundCorners([.bottomLeft, .bottomRight, .topLeft], radius: 16)
Foxing answered 6/12, 2019 at 10:10 Comment(1)
I just came up with a simple to use extension with the help of all of the answers provided here. Glad to hear that it helped you.Foxing
S
4
extension UIView {

func roundCorners(_ corners: CACornerMask, radius: CGFloat) {
    if #available(iOS 11, *) {
        self.layer.cornerRadius = radius
        self.layer.maskedCorners = corners
    } else {
        var cornerMask = UIRectCorner()
        if(corners.contains(.layerMinXMinYCorner)){
            cornerMask.insert(.topLeft)
        }
        if(corners.contains(.layerMaxXMinYCorner)){
            cornerMask.insert(.topRight)
        }
        if(corners.contains(.layerMinXMaxYCorner)){
            cornerMask.insert(.bottomLeft)
        }
        if(corners.contains(.layerMaxXMaxYCorner)){
            cornerMask.insert(.bottomRight)
        }
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: cornerMask, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }
}

}

Shandishandie answered 15/10, 2019 at 9:37 Comment(1)
this should be the accepted answer for the newest iOS versions, thanks it works for meMariano
S
1

issue solved right top and right bottom work now

Tested code in iOS 9 , 10 , 11 version

 extension UIView {
        func roundCorners(_ corners:UIRectCorner,_ cormerMask:CACornerMask, radius: CGFloat) {
            if #available(iOS 11.0, *){
                self.clipsToBounds = false
                self.layer.cornerRadius = radius
                self.layer.maskedCorners = cormerMask
            }else{
                let rectShape = CAShapeLayer()
                rectShape.bounds = self.frame
                rectShape.position = self.center
                rectShape.path = UIBezierPath(roundedRect: self.bounds,    byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)).cgPath
                self.layer.mask = rectShape
            }
        }
        
    }
Stare answered 15/5, 2018 at 7:37 Comment(1)
Not working for IOS 9. Corner border cuts on radius portionDoubletree
P
0

As @kazi.munshimun gave a view-only setup suggestion, it is wonderful, however I didn't want create a whole view for this, and I was looking for a one-only field for cornerRadius.

So I came up with the idea of flag combinations where for example BottomLeft(4) + BottomRight(8) = 12

Therefore, it needs on your view to set up the number combination from 0 (none) to 15 (all of corners) + clipsToBounds enabled. And that's it ! Entirely customizable through file.

This solution example works for iOS 11.0+ (Swift 4+) It can be adapted for lower versions :

extension UIView {
    enum CornerEnum: Int  {
        case None = 0
        case TopLeft = 1
        case TopRight = 2
        case BottomLeft = 4
        case BottomRight = 8
    }
    
    @IBInspectable
    var radiusCorners: Int {
        set {
            var corners = CACornerMask()
            if(newValue & CornerEnum.TopLeft.rawValue != 0){
                corners.insert(.layerMinXMinYCorner)
            }
            if(newValue & CornerEnum.TopRight.rawValue != 0){
                corners.insert(.layerMaxXMinYCorner)
            }
            if(newValue & CornerEnum.BottomLeft.rawValue != 0){
                corners.insert(.layerMinXMaxYCorner)
            }
            if(newValue & CornerEnum.BottomRight.rawValue != 0){
                corners.insert(.layerMaxXMaxYCorner)
            }
            layer.maskedCorners = corners
        }
        get { return self.radiusCorners }
    }
}
Phosphocreatine answered 27/7, 2022 at 0:32 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.