添加多个阴影隐藏背景颜色和文本 UIButton

Adding multiple shadows hides the background colour and text UIButton

我试图向我的 UIButton 添加多个阴影。如图所示,添加了两个阴影。但是,它们隐藏了 UIButton 的标题和背景颜色。为什么会这样?那么,图层的顺序是不是变成了bottomLayer、topLayer、text和background?

实际结果

预期结果

这是我的 UIButton class 的样子。

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
    }
    
}

您好,下面的代码会对您有所帮助,我在按钮阴影中得到了您想要的确切结果

用我的代码替换一些功能,

您的代码:

override func layoutSubviews() {

    super.layoutSubviews()
    addDropShadow()
}

换成我的代码:

 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)
    }

您的代码:

 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
}

将其替换为以下代码:

 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

    }

不需要你private func createShadowLayer(color: UIColor, offset: CGSize) -> CALayer

您可以删除该功能。

并确保您的按钮类型是自定义的

我能够解决问题如下:

我没有使用 addSublayer(_ layer: CALayer) 方法添加图层,而是使用了 insertSublayer(_ layer: CALayer, at idx: UInt32) 方法。

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))

        // Modified
        layer.insertSublayer(topLayer, at: 0)
        layer.insertSublayer(bottomLayer, at: 0)
    }

此外,在您的 createShadowLayer 方法中,我返回了一个 CAShapeLayer,而不是 CALayer。

private func createShadowLayer(color: UIColor, offset: CGSize) -> CAShapeLayer {
        // Modified
        let shadowLayer = CAShapeLayer()
        shadowLayer.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.cornerRadius).cgPath
        shadowLayer.fillColor = self.backgroundColor?.cgColor
        shadowLayer.shadowPath = shadowLayer.path
        
//        shadowLayer.masksToBounds = false
        shadowLayer.shadowColor = color.cgColor
        shadowLayer.shadowOpacity = 1
        shadowLayer.shadowOffset = offset
        shadowLayer.shadowRadius = 10
//        shadowLayer.shouldRasterize = true

        return shadowLayer
    }

我不知道这两个更改是否必要。但这就是它对我有用的方式:)