Search code examples
swiftuibuttonswift4swift5

Adding multiple shadows hides the background colour and text UIButton


I was trying to add multiple shadows to my UIButton. The two shadows were added as you can see in the image. However, they hide the title and background colour of UIButton. Why is this happening? So, has the order of the layers become bottomLayer, topLayer, text and background?

The actual result

enter image description here

The expected Result

enter image description here

This is how my UIButton class looks.

class PrimaryButton: UIButton {
    
    let cornerRadius: CGFloat = 10
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    convenience init() {
        self.init(frame: .zero)
        configure()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        addDropShadow()
    }
    
    private func configure() {
        backgroundColor = .white;
        layer.cornerRadius = cornerRadius
        
        setTitle("Get Followers", for: .normal)
        setTitleColor(Colours.buttonTextColour, for: .normal)
    }

    private func addDropShadow() {
        let topLayer = createShadowLayer(color: Colours.shadowWhite, offset: CGSize(width: -6, height: -6))
        let bottomLayer = createShadowLayer(color: Colours.shadowBlack, offset: CGSize(width: 6, height: 6))
        
        layer.addSublayer(topLayer)
        layer.addSublayer(bottomLayer)
    }
    
    private func createShadowLayer(color: UIColor, offset: CGSize) -> CALayer {
        let shadowLayer = CALayer()
        shadowLayer.masksToBounds = false
        shadowLayer.shadowColor = color.cgColor
        shadowLayer.shadowOpacity = 1
        shadowLayer.shadowOffset = offset
        shadowLayer.shadowRadius = 10
        shadowLayer.shouldRasterize = true
        shadowLayer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: 10).cgPath
        
        return shadowLayer
    }
    
}

Solution

  • Hello below code will help you, I got exact result what you want in button shadow

    just replace some function with my code,

    Your code:

    override func layoutSubviews() {
    
        super.layoutSubviews()
        addDropShadow()
    }
    

    Replace it with my code:

     override func layoutSubviews() {
            super.layoutSubviews()
            addDropShadow(color: UIColor.red, offset: CGSize(width: -6, height: -6), btnLayer: self.layer)
            addDropShadow(color: UIColor.blue, offset: CGSize(width: 6, height: 6), btnLayer: self.layer)
        }
    

    Your code:

     private func addDropShadow() {
            let topLayer = createShadowLayer(color: Colours.shadowWhite, offset: CGSize(width: -6, height: -6))
            let bottomLayer = createShadowLayer(color: Colours.shadowBlack, offset: CGSize(width: 6, height: 6))
    
        layer.addSublayer(topLayer)
        layer.addSublayer(bottomLayer)
    }
    
    private func createShadowLayer(color: UIColor, offset: CGSize) -> CALayer {
        let shadowLayer = CALayer()
        shadowLayer.masksToBounds = false
        shadowLayer.shadowColor = color.cgColor
        shadowLayer.shadowOpacity = 1
        shadowLayer.shadowOffset = offset
        shadowLayer.shadowRadius = 10
        shadowLayer.shouldRasterize = true
        shadowLayer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: 10).cgPath
    
        return shadowLayer
    }
    

    Replace it with below code:

     private func addDropShadow(color: UIColor, offset: CGSize, btnLayer : CALayer)
        {
    
            btnLayer.masksToBounds = false
            btnLayer.shadowColor = color.cgColor
            btnLayer.shadowOpacity = 1
            btnLayer.shadowOffset = offset
            btnLayer.shadowRadius = 10
    
        }
    

    no need to you private func createShadowLayer(color: UIColor, offset: CGSize) -> CALayer

    you can remove that function.

    and make sure your button type is custom