Ios 如何将渐变边框颜色应用于UIButton?

Ios 如何将渐变边框颜色应用于UIButton?,ios,uibutton,gradient,Ios,Uibutton,Gradient,我想实现这样的目标。我已经找过了。我得到的建议是,我可以在按钮后面放置一个高度和宽度都大于按钮的渐变视图。但我想要精确的角半径和带有渐变的边框颜色 extension CALayer { func addGradienBorder(colors:[UIColor],width:CGFloat = 1) { let gradientLayer = CAGradientLayer() gradientLayer.frame = CGRect(origin:

我想实现这样的目标。我已经找过了。我得到的建议是,我可以在按钮后面放置一个高度和宽度都大于按钮的渐变视图。但我想要精确的角半径和带有渐变的边框颜色

extension CALayer {
    func addGradienBorder(colors:[UIColor],width:CGFloat = 1) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame =  CGRect(origin: CGPointZero, size: self.bounds.size)
        gradientLayer.startPoint = CGPointMake(0.0, 0.5)
        gradientLayer.endPoint = CGPointMake(1.0, 0.5)
        gradientLayer.colors = colors.map({$0.CGColor})

        let shapeLayer = CAShapeLayer()
        shapeLayer.lineWidth = width
        shapeLayer.path = UIBezierPath(rect: self.bounds).CGPath
        shapeLayer.fillColor = nil
        shapeLayer.strokeColor = UIColor.blackColor().CGColor
        gradientLayer.mask = shapeLayer

        self.addSublayer(gradientLayer)
    }

您可以创建自己的
BorderedButton
子类,该子类将:

  • 添加梯度子层
  • 创建由边界路径组成的形状层;及
  • 将该形状层用作渐变层的遮罩,以在路径形状中生成渐变边界
例如:

请注意:

  • 我更新渐变层的
    ,以及
    布局子视图
    方法中用作
    遮罩
    的路径,该方法可确保在大小更改时正确渲染边框(例如,使用约束来定义视图的大小)
  • 我已将此
    @IBDesignable
    设置为可设计,这样您甚至可以将其添加到情节提要中,并可以看到它正确呈现
  • 我已经将
    cornerRadius
    lineWidth
    设置为
    @IBInspectable
    ,这样您就可以在IB中调整它们(因为它们有设置“需要布局”的
    didSet
    观察者,它们将确保可以在故事板中观察到更改)
无论如何,这会产生:


你看过这个答案了吗?
@IBDesignable
class BorderedButton: UIButton {
    @IBInspectable var lineWidth:    CGFloat = 3  { didSet { setNeedsLayout() } }
    @IBInspectable var cornerRadius: CGFloat = 10 { didSet { setNeedsLayout() } }

    let borderLayer: CAGradientLayer = {
        let borderLayer = CAGradientLayer()
        borderLayer.type = .axial
        borderLayer.colors = [#colorLiteral(red: 0.6135130525, green: 0.3031745553, blue: 0.9506058097, alpha: 1).cgColor, #colorLiteral(red: 0.9306473136, green: 0.1160953864, blue: 0.8244602084, alpha: 1).cgColor]
        borderLayer.startPoint = CGPoint(x: 0, y: 1)
        borderLayer.endPoint = CGPoint(x: 1, y: 0)
        return borderLayer
    }()

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        configure()
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        borderLayer.frame = bounds

        let mask = CAShapeLayer()
        let rect = bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2)
        mask.path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
        mask.lineWidth = lineWidth
        mask.fillColor = UIColor.clear.cgColor
        mask.strokeColor = UIColor.white.cgColor
        borderLayer.mask = mask
    }
}

private extension BorderedButton {
    func configure() {
        layer.addSublayer(borderLayer)
    }
}