Как применить цвет градиента к UIButton? - PullRequest
0 голосов
/ 02 ноября 2019

Я хочу добиться чего-то подобного. Я искал это. Я получаю предложения, что я могу поместить градиентный вид за кнопку с высотой и шириной больше, чем кнопка. Но я хочу точный радиус угла и цвет границы с градиентами.

sample image

Ответы [ 2 ]

1 голос
/ 02 ноября 2019

Вы можете создать свой собственный подкласс BorderedButton, который будет:

  • Добавить подслой градиента;
  • Создать слой формы, состоящий из пути границы;И
  • Используйте этот слой формы как маску для слоя градиента, чтобы получить границу градиента в форме пути.

Например:

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

Обратите внимание, что:

  • Я обновляю frame слоя градиента и путь, который используется как mask внутри метода layoutSubviews, что обеспечивает правильную визуализацию границы при изменении размера(например, вы используете ограничения для определения размера представления).
  • Я сделал это @IBDesignable, так что вы даже можете добавить это в раскадровку, и вы увидите, что оно отображается правильно.
  • Я сделал cornerRadius и lineWidth равными @IBInspectable, чтобы вы могли настроить их в IB (и поскольку у них есть didSet наблюдателей, которые устанавливают «нужное расположение», они обеспечатчто изменения наблюдаются в раскадровке).

В любом случае, это дает:

enter image description here

0 голосов
/ 02 ноября 2019
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)
    }
...