【问题标题】:UIButton with background image, rounded corners and a shadow带有背景图像、圆角和阴影的 UIButton
【发布时间】:2020-10-25 16:56:42
【问题描述】:

我正在尝试创建一个带有圆角、背景图像和阴影的 UIButton。在添加阴影之前,一切正常。

但添加阴影值后,阴影不显示。显然是由于clipsToBounds 属性值被设置为true。如果我删除它,它看起来像这样。

因为我也需要圆角半径,所以我不能将 clipsToBounds 设为 false

这是我的代码。

class CustomButton: UIButton {
    
    var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            clipsToBounds = true
        }
    }
    
    var shadowRadius: CGFloat {
        get {
            return layer.shadowRadius
        }
        set {
            layer.shadowRadius = newValue
        }
    }
    
    var shadowOpacity: Float {
        get {
            return layer.shadowOpacity
        }
        set {
            layer.shadowOpacity = newValue
        }
    }
    
    var shadowOffset: CGSize {
        get {
            return layer.shadowOffset
        }
        set {
            layer.shadowOffset = newValue
        }
    }
    
    var shadowColor: UIColor? {
        get {
            if let color = layer.shadowColor {
                return UIColor(cgColor: color)
            }
            return nil
        }
        set {
            if let color = newValue {
                layer.shadowColor = color.cgColor
            } else {
                layer.shadowColor = nil
            }
        }
    }
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        
    }
    
}


private lazy var button: CustomButton = {
    let button = CustomButton()
    button.translatesAutoresizingMaskIntoConstraints = false
    button.setBackgroundImage(UIImage(named: "Rectangle"), for: .normal)
    button.setTitleColor(.white, for: .normal)
    button.setTitle("Sign Up", for: .normal)
    button.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: .semibold)
    button.cornerRadius = 20
    button.shadowColor = .systemGreen
    button.shadowRadius = 10
    button.shadowOpacity = 1
    button.shadowOffset = CGSize(width: 0, height: 0)
    return button
}()

是否有一种解决方法可以同时使用阴影和圆角半径?

Demo project

【问题讨论】:

    标签: ios swift calayer shadow rounded-corners


    【解决方案1】:

    您可以通过添加不同图层的阴影和背景图像来实现。

    首先,如果您不需要这些属性,请删除所有属性并修改您的 CustomButton 实现,如下所示(根据需要修改):

    class CustomButton: UIButton {
        
        private let cornerRadius: CGFloat = 20
        private var imageLayer: CALayer!
        private var shadowLayer: CALayer!
        
        override func draw(_ rect: CGRect) {
            addShadowsLayers(rect)
        }
        
        private func addShadowsLayers(_ rect: CGRect) {
            // Add Image
            if self.imageLayer == nil {
                let imageLayer = CALayer()
                imageLayer.frame = rect
                imageLayer.contents = UIImage(named: "Rectangle")?.cgImage
                imageLayer.cornerRadius = cornerRadius
                imageLayer.masksToBounds = true
                layer.insertSublayer(imageLayer, at: 0)
                self.imageLayer = imageLayer
            }
            
            // Set the shadow
            if self.shadowLayer == nil {
                let shadowLayer = CALayer()
                shadowLayer.masksToBounds = false
                shadowLayer.shadowColor = UIColor.systemGreen.cgColor
                shadowLayer.shadowOffset = .zero
                shadowLayer.shadowOpacity = 1
                shadowLayer.shadowRadius = 10
                shadowLayer.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
                layer.insertSublayer(shadowLayer, at: 0)
                self.shadowLayer = shadowLayer
            }
        }
    }
    

    然后像下面这样初始化你的按钮:

    private lazy var button: CustomButton = {
        let button = CustomButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitleColor(.white, for: .normal)
        button.setTitle("Sign Up", for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: .semibold)
        return button
    }()
    

    【讨论】:

    • 谢谢。这很棒。但问题是,如果我删除属性,我最终会硬编码按钮类本身的值。我希望使它更像是一个通用的解决方案。所以我可以在初始化按钮时设置阴影/背景图像值。
    • 更新:我通过公开属性修改了您的代码,例如 this。仍然工作得很好。但是我注意到阴影有一个小问题。如果我减小阴影半径,阴影没有相同的角半径。 See。知道为什么会这样吗?这个问题也存在于原始代码中。我也尝试将cornerRadius 值添加到shadowLayer,但这并没有改变任何东西。
    • 您是否为两者指定了相同的半径?我为此做了一个小更新。 (顺便说一句,我无法访问第一个链接)。您可以根据需要编辑/扩展代码的任何部分,我只保留我所做的所需部分。
    • 请立即查看。 linkcornerRadiusshadowRadius 是不同的,对吧?由于阴影半径处理阴影的模糊半径,所以我将其设置为 2。那时我注意到阴影的方形边缘。拐角半径仍设置为 20。这没有问题。
    • 是的,你是对的,我修改了shadowLayer.shadowPath 行。
    【解决方案2】:

    您需要为阴影和图像使用两个单独的视图。我找不到使用相同按钮层设置图像、阴影和角半径的任何解决方案。

    使按钮的圆角半径(clipsToBounds=true) 变圆并在其上设置图像。

    在按钮下方以适当的阴影半径和偏移量拍摄阴影视图。

    【讨论】:

      【解决方案3】:

      可以添加 view.layer.masksToBounds = false

      这将禁用子图层的剪辑

      https://developer.apple.com/documentation/quartzcore/calayer/1410896-maskstobounds

      【讨论】:

        猜你喜欢
        • 2012-04-29
        • 2023-04-01
        • 1970-01-01
        • 2020-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-11
        • 2020-03-24
        相关资源
        最近更新 更多