4

I need to create a button with top-left & bottom-left corner radius like this one enter image description here. I tried by creating the following extension that was taken from one of stackoverflow answer:

extension UIButton {

   func roundCorners(corners:UIRectCorner, radius: CGFloat) {
       self.layer.borderColor = GenerateShape.UIColorFromHex(0x989898, alpha: (1.0-0.3)).CGColor
       self.layer.borderWidth = 1.0
       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

   }
}

then called the method like this:

self.collectionBtn.roundCorners(.TopLeft | .BottomLeft, radius: cornerRadius) 

this code generates the following shape enter image description here

So why the top-left & bottom-left corner invisible? What should I do to make them visible?

Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
Linkon Sid
  • 521
  • 1
  • 5
  • 16

2 Answers2

7

Your code is applying a mask layer to your button. that causes anything outside the shape you install in the mask layer to be masked away. When you install a path with rounded corners, it essentially "shaves off" the 2 corners. That's not what you want.

You probably want to create a shape layer and install it as a regular sublayer of your button's layer, not as the mask layer. You'll need to set the fill color to clear however.

Change your code like this:

extension UIButton 
{
  func roundCorners(corners:UIRectCorner, radius: CGFloat) 
  {
    let borderLayer = CAShapeLayer()
    borderLayer.frame = self.layer.bounds
    borderLayer.strokeColor = GenerateShape.UIColorFromHex(0x989898, 
      alpha: (1.0-0.3)).CGColor
    borderLayer.fillColor = UIColor.clearColor().CGColor
    borderLayer.lineWidth = 1.0
    let path = UIBezierPath(roundedRect: self.bounds, 
      byRoundingCorners: corners, 
      cornerRadii: CGSize(width: radius, height: radius))
    borderLayer.path = path.CGPath
    self.layer.addSublayer(borderLayer);
  }
}

EDIT:

Your syntax for setting the corners won't work in Swift 2:

self.collectionBtn.roundCorners(.TopLeft | .BottomLeft, radius: 10)

Should be

self.collectionBtn.roundCorners([.TopLeft, .BottomLeft], radius: 10)
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • great. that works nicely. please do me a favor. I modified the code to fill the button with gray color using following code: borderLayer.fillColor = UIColor.lightGrayColor().CGColor. that works. now I need to set the button title color to white. I use the following code: button.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal). but the title color doesn't change. color remains gray which I've set from storyboard. can u tell me why it's not changing?? – Linkon Sid Oct 05 '15 at 18:35
  • Post your entire method that sets button color at the end of your question. What is "button"? – Duncan C Oct 05 '15 at 19:15
  • inside the roundCorners() method of UIButton extension at first line I add this code : self.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal) – Linkon Sid Oct 06 '15 at 06:12
  • borderLayer.fillColor = GenerateShape.UIColorFromHex(0x989898, alpha: (1.0-0.3)).CGColor that's the code that sets button color – Linkon Sid Oct 06 '15 at 14:58
  • I'm having some trouble with this code. Mainly, my compiler is giving me this error on the line "self.layer.addSublayer(borderLayer.path)" : "Cannot convert value of type CGPath? to expected argument type CGLayer". Any suggestions? – David Tamrazov Aug 04 '16 at 17:32
  • That's a typo. It should be `self.layer.addSublayer(borderLayer)`. – Duncan C Aug 04 '16 at 23:55
0

Here is how you can do it:

CGRect maskRect = CGRectMake(0.0, 0.0, CGRectGetWidth(<#something here#>), CGRectGetHeight(<#something here#>));
CAShapeLayer *maskLayer = [CAShapeLayer layer];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:maskRect
                                           byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerTopLeft)
                                                 cornerRadii:CGSizeMake(<#corner radius#>, <#corner radius#>)];
maskLayer.path = path.CGPath;
self.layer.mask = maskLayer;
Soberman
  • 2,556
  • 1
  • 19
  • 22
  • Nope. That will give the same results as the OPs code. If you want rounded corners on your button you don't want a mask layer, you want a shape layer that is a regular sublayer. – Duncan C Oct 04 '15 at 19:39
  • Look closer. It is a `CAShapeLayer`. – Soberman Oct 04 '15 at 19:40
  • 1
    Yes, but you are installing the shape layer as the mask of the button's layer, which will not give the desired result. Try it. It won't work as the way you think it will. See my answer. – Duncan C Oct 04 '15 at 19:45