dang
dang

Reputation: 2412

Swift - Apply Shadow to circular button on click

I am creating circular buttons as follow:

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
            let button = GradientButton.createCircularButton(20, yPos: 20, width: 30, height: 30, circleValue:20)

        button.addTarget(self, action: #selector(ViewController.didCircleBtnTouched(_:)), forControlEvents: UIControlEvents.TouchUpInside)
        self.view.addSubview(button)
  }
 }


enum ColorType {
    case red, green, orange
}

class GradientButton: UIButton {
    var colorType: ColorType?   


public class func createCircularButton(xPos: CGFloat, yPos: CGFloat, width: CGFloat, height: CGFloat, circleValue: Int) -> GradientButton {
    let button = GradientButton()

    button.titleLabel!.font =  UIFont(name:"HelveticaNeue", size: 12)
    let buttonFrame = CGRect(x: xPos, y: yPos, width: width, height: height)

    button.frame = buttonFrame

    button.backgroundColor = UIColor.clearColor()
    button.backgroundColor = UIColor.whiteColor()


    button.layer.borderWidth = 1
    button.layer.cornerRadius = 15.0
    //this helps making it circular not rectangle
    button.clipsToBounds = true


    let red = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)//red
    let green = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)//green
    let orange = UIColor(red:243/255, green:144/255, blue:25/255, alpha:1.0)//orange

    if(circleValue <= 3){
        button.colorType = .green
        button.layer.borderColor = UIColor.greenColor().CGColor
        button.setTitleColor(green, forState: .Normal)
    } else if(circleValue > 3 && circleValue <= 7){
        button.colorType = .orange
        button.layer.borderColor = UIColor.orangeColor().CGColor
        button.setTitleColor(orange, forState: .Normal)
    } else if(circleValue > 7){
        button.colorType = .red
        button.layer.borderColor = UIColor.redColor().CGColor
        button.setTitleColor(red, forState: .Normal)

    }       
    button.setTitle("\(circleValue)", forState: .Normal)
    return button
}
}

And on click of button I am applying gradient as follow:

 func didCircleBtnTouched(sender:GradientButton!){
             ApplyGradientToButton(sender)
 }



func ApplyGradientToButton(sender: GradientButton!){
    var color1 = UIColor()
    var color2 = UIColor()

   if(sender.colorType == .red){
        color1 = UIColor(red:134/255, green:16/255, blue:1/255, alpha:1.0)
        color2 = UIColor(red:200/255, green:37/255, blue:6/255, alpha:1.0)
    }
    else if(sender.colorType == .green) {
        color1 = UIColor(red:0/255, green:136/255, blue:43/255, alpha:1.0)
        color2 = UIColor(red:112/255, green:191/255, blue:65/255, alpha:1.0)
    }
    else if(sender.colorType == .orange) {
        color1 = UIColor(red:200/255, green:110/255, blue:1/255, alpha:1.0)
        color2 = UIColor(red:239/255, green:149/255, blue:26/255, alpha:1.0)

    }

    sender.setTitleColor(UIColor.whiteColor(), forState: .Normal)

    var layer = sender.layer

    layer.shadowColor = UIColor.blackColor().CGColor
    layer.shadowOffset = CGSize(width: 0.0, height: 5.0)
    layer.shadowOpacity = 1.0
    layer.shadowRadius = 10.0


    sender.applyGradient([color2, color1], locations: [0.0, 0.90])
}

I need to display shadow around circular button on button click. But shadow is not getting displayed. I think button.clipsToBounds = true is responsible as when I am not using this property shadow appears. Unfortunately by removing this property my circular button becomes rectangular after click which is not desirable.

Is there any way to display the shadow without changing the shape of button? Please advise?

Current output:

Current

Expected output:

Expected

Upvotes: 1

Views: 8193

Answers (2)

NiravS
NiravS

Reputation: 1284

Just Put this code in viewController.swift file.. (Or any other file)

extension UIView {
    func setRadiusWithShadow(_ radius: CGFloat? = nil) {
        self.layer.cornerRadius = radius ?? self.frame.width / 2
        self.layer.shadowColor = UIColor.darkGray.cgColor
        self.layer.shadowOffset = CGSize(width: 1.5, height: 1.5)
        self.layer.shadowRadius = 1.0
        self.layer.shadowOpacity = 0.7
        self.layer.masksToBounds = false
    }

}

and then apply to your button..

btnEdit.setRadiusWithShadow()

Yeah... Just see the output... Everything is done...

Note: You can change CGSize(width: 1.5, height: 1.5) values as per your desired need...

Upvotes: 0

Lefteris
Lefteris

Reputation: 14677

Well you can't clip/mask to bounds and add a shadow, as it will also be clipped or masked too.

The solution is to add the shadow on a separate layer and add the image as a sublayer.

This is described in many posts here:

https://stackoverflow.com/a/25591916/312312

Swift - Problems with corner radius and drop shadow

and many many more

Upvotes: 6

Related Questions