Problems with corner radius and drop shadow for button

cornerradius, ios, shadow, swift, uibutton

Solution

The following Swift 5 / iOS 12 code shows how to set a subclass of `UIButton` that allows to create instances with rounded corners and shadow around it:

import UIKit

final class CustomButton: UIButton {

    private var shadowLayer: CAShapeLayer!

    override func layoutSubviews() {
        super.layoutSubviews()

        if shadowLayer == nil {
            shadowLayer = CAShapeLayer()
            shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 12).cgPath
            shadowLayer.fillColor = UIColor.white.cgColor

            shadowLayer.shadowColor = UIColor.darkGray.cgColor
            shadowLayer.shadowPath = shadowLayer.path
            shadowLayer.shadowOffset = CGSize(width: 2.0, height: 2.0)
            shadowLayer.shadowOpacity = 0.8
            shadowLayer.shadowRadius = 2

            layer.insertSublayer(shadowLayer, at: 0)
            //layer.insertSublayer(shadowLayer, below: nil) // also works
        }        
    }

}

According to your needs, you may add a `UIButton` in your Storyboard and set its class to `CustomButton` or you may create an instance of `CustomButton` programmatically. The following `UIViewController` implementation shows how to create and use a `CustomButton` instance programmatically:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = CustomButton(type: .system)
        button.setTitle("Button", for: .normal)
        view.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)        
        let widthConstraint = button.widthAnchor.constraint(equalToConstant: 100)
        let heightConstraint = button.heightAnchor.constraint(equalToConstant: 100)
        NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
    }

}

The previous code produces the image below in the iPhone simulator:

Problem

I'm trying to create a button with rounded corners and a drop shadow. No matter how I switch up, the button will not display correctly. I've tried `masksToBounds = false` and `masksToBounds = true`, but either the corner radius works and the shadow does not or the shadow works and the corner radius doesn't clip the corners of the button. ``` import UIKit import QuartzCore @IBDesignable class Button : UIButton { @IBInspectable var masksToBounds: Bool = false {didSet{updateLayerProperties()}} @IBInspectable var cornerRadius : CGFloat = 0 {didSet{updateLayerProperties()}} @IBInspectable var borderWidth : CGFloat = 0 {didSet{updateLayerProperties()}} @IBInspectable var borderColor : UIColor = UIColor.clearColor() {didSet{updateLayerProperties()}} @IBInspectable var shadowColor : UIColor = UIColor.clearColor() {didSet{updateLayerProperties()}} @IBInspectable var shadowOpacity: CGFloat = 0 {didSet{updateLayerProperties()}} @IBInspectable var shadowRadius : CGFloat = 0 {didSet{updateLayerProperties()}} @IBInspectable var shadowOffset : CGSize = CGSizeMake(0, 0) {didSet{updateLayerProperties()}} override func drawRect(rect: CGRect) { updateLayerProperties() } func updateLayerProperties() { self.layer.masksToBounds = masksToBounds self.layer.cornerRadius = cornerRadius self.layer.borderWidth = borderWidth self.layer.borderColor = borderColor.CGColor self.layer.shadowColor = shadowColor.CGColor self.layer.shadowOpacity = CFloat(shadowOpacity) self.layer.shadowRadius = shadowRadius self.layer.shadowOffset = shadowOffset } } ```

Original source

Related problems