Search code examples
swiftbuttonconstraintsscaleshadow

Swift - Custom button class shadow size scaling not working


I've wrote this custom button class

class RoundedButton: UIButton {

override func awakeFromNib() {

    layer.cornerRadius = 5

    layer.shadowColor = UIColor.black.cgColor
    layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
    layer.shadowOpacity = 0.2
    layer.shadowRadius = 1.0
    layer.masksToBounds = false
    layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 5).cgPath

    layer.contents = center
    layer.shouldRasterize = true
    layer.rasterizationScale = UIScreen.main.scale
}
}

On my iPhone X everything perfectly fits

enter image description here

But when I'm using a device with smaller screen, the shadow don't scale correctly according to the button size.

enter image description here

Is there a problem with the button class itself or is it a constraints problem? I can't find a solution.


Solution

  • You need to update the shadow on layoutSubviews (this should also resolve issues your code seemed to have with rotation).

    class RoundedButton: UIButton {
        override func layoutSubviews() {
            super.layoutSubviews()
            updateShadow(on: self)
        }
    
    func updateShadow(on background: UIView) {
        let layer = background.layer
        layer.shadowPath = UIBezierPath(rect: background.bounds).cgPath
        layer.masksToBounds = false
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 0.0)
        layer.shadowRadius = 4
        layer.shadowOpacity = 0.22
    }
    
    override func awakeFromNib() {
    
        layer.cornerRadius = 5
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
        layer.shadowOpacity = 0.2
        layer.shadowRadius = 1.0
        layer.masksToBounds = false
        layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 5).cgPath
        layer.contents = center
        layer.shouldRasterize = true
        layer.rasterizationScale = UIScreen.main.scale
    }
    }
    

    Hope this helps you