Кнопка iOS с неравномерным цветом [дубликат]

Ответ Dawood ibn Kareem работал для меня, но у меня не было примера, также я использую Kotlin и Mockito-Kotlin , поэтому мое решение таково:

class Foo(var mutable: String)

interface Bar {
    fun run(foo: Foo)
}

@Test fun `validate mutable parameter at invocation`() {
    val bar = mock()

    var valueAtInvocation: String? = null
    whenever(bar.run(any())).then {
        val foo = it.arguments.first() as Foo
        valueAtInvocation = foo.mutable // Store mutable value as it was at the invocation
        Unit // The answer
    }

    val foo = Foo(mutable = "first")
    bar.run(foo)
    valueAtInvocation isEqualTo "first"

    foo.mutable = "second"
    bar.run(foo)
    valueAtInvocation isEqualTo "second"
}

valueAtInvocation будет представлять значение изменяемого свойства foo.mutable при последнем вызове bar.run(foo). Также возможно делать утверждения в блоке then {}.

10
задан Michael Yaworski 19 June 2016 в 01:22
поделиться

5 ответов

Ваш код работает нормально. Вам просто нужно помнить, чтобы каждый раз устанавливать рамку градиента. Лучше всего просто сделать категорию градиента также заданной для вас рамкой представления.

Таким образом, вы не забудете, и оно применяется отлично.

extension UIView {
    func applyGradient(colours: [UIColor]) -> Void {
        self.applyGradient(colours, locations: nil)
    }

    func applyGradient(colours: [UIColor], locations: [NSNumber]?) -> Void {
        let gradient: CAGradientLayer = CAGradientLayer()
        gradient.frame = self.bounds
        gradient.colors = colours.map { $0.CGColor }
        gradient.locations = locations
        self.layer.insertSublayer(gradient, atIndex: 0)
    }
}

class ViewController: UIViewController {

    @IBOutlet weak var btn: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.btn.titleLabel?.textColor = UIColor.whiteColor()

        self.btn.applyGradient([UIColor.yellowColor(), UIColor.blueColor()])
        self.view.applyGradient([UIColor.yellowColor(), UIColor.blueColor(), UIColor.redColor()], locations: [0.0, 0.5, 1.0])
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

Кнопки Просмотры. Вы применяете к нему градиенты так же, как и к другому виду.

31
ответ дан Brandon 16 August 2018 в 00:34
поделиться
  • 1
    Я не согласен с последним предложением. В то время как кнопки являются видами, фон кнопки не совпадает с фоном представления. Фон кнопки может меняться в зависимости от состояния кнопки. При добавлении градиента в качестве слоя мы теряем этот эффект. Идеальное решение состоит в том, чтобы захватить слой градиента в изображение, задав изображение как фоновое изображение кнопки. Другая проблема заключается в том, что границы слоев должны обновляться всегда, когда изменяется рамка кнопки, то есть от layoutSubviews. – Sulthan 28 July 2017 в 18:36

Я пробовал все из них, это моя кнопка init внутри viewdidload

let button = UIButton()
    button.setTitle("Alper", for: .normal)
    button.layer.borderColor = UIColor.white.cgColor
    button.layer.borderWidth = 1
    view.addSubview(button)
    button.anchor(top: nil, left: nil, bottom: logo.topAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, height: 50, width: 100)
    let gradientx = CAGradientLayer()
    gradientx.colors = [UIColor.blue,UIColor.red]
    gradientx.startPoint = CGPoint(x: 0.0, y: 0.5)
    gradientx.endPoint = CGPoint(x: 1.0, y: 1.0)
    gradientx.frame = button.bounds
    button.layer.insertSublayer(gradientx, at: 0)

anchor - это расширение, поэтому это неуместный градиент.

1
ответ дан Alper 16 August 2018 в 00:34
поделиться

@Zeb ответ велик, но просто очистить его и сделать его немного более осторожным. Вычислимые свойства только для чтения должны избегать использования get и return Void избыточно:

typealias GradientPoints = (startPoint: CGPoint, endPoint: CGPoint)

enum GradientOrientation {
  case topRightBottomLeft
  case topLeftBottomRight
  case horizontal
  case vertical

var startPoint: CGPoint {
    return points.startPoint
}

var endPoint: CGPoint {
    return points.endPoint
}

var points: GradientPoints {
    switch self {
    case .topRightBottomLeft:
        return (CGPoint.init(x: 0.0, y: 1.0), CGPoint.init(x: 1.0, y: 0.0))
    case .topLeftBottomRight:
        return (CGPoint.init(x: 0.0, y: 0.0), CGPoint.init(x: 1, y: 1))
    case .horizontal:
        return (CGPoint.init(x: 0.0, y: 0.5), CGPoint.init(x: 1.0, y: 0.5))
    case .vertical:
        return (CGPoint.init(x: 0.0, y: 0.0), CGPoint.init(x: 0.0, y: 1.0))
    }
  }
}

extension UIView {

func applyGradient(withColours colours: [UIColor], locations: [NSNumber]? = nil) {
    let gradient: CAGradientLayer = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.colors = colours.map { $0.cgColor }
    gradient.locations = locations
    self.layer.insertSublayer(gradient, at: 0)
}

func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) {
    let gradient: CAGradientLayer = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.colors = colours.map { $0.cgColor }
    gradient.startPoint = orientation.startPoint
    gradient.endPoint = orientation.endPoint
    self.layer.insertSublayer(gradient, at: 0)
  }
}
4
ответ дан brl214 16 August 2018 в 00:34
поделиться
  • 1
    Это прекрасно работает, я попытался установить UIButton cornerRadius, но его не получило никакого эффекта, если я не удаляю градиент, есть ли способ решить это? – SimpiMind 12 April 2017 в 15:40
  • 2
    Вы пытались установить masksToBounds = false – brl214 12 April 2017 в 17:07

Для Swift 2.0 для получения цвета градиентов для UIButton

let gradient: CAGradientLayer = CAGradientLayer()

gradient.colors = [(UIColor(red: 59.0/255.0, green: 187.0/255.0, blue: 182.0/255.0, alpha: 1.00).CGColor), (UIColor(red: 57.0/255.0, green: 174.0/255.0, blue: 236.0/255.0, alpha: 1.00).CGColor)]
gradient.locations = [0.0 , 1.0]

gradient.startPoint = CGPoint(x: 0.0, y: 1.0)
gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
gradient.frame = CGRect(x: 0.0, y: 0.0, width: btn.frame.size.width, height: btn.frame.size.height)
btn.layer.insertSublayer(gradient, atIndex: 0)
1
ответ дан Hardik Thakkar 16 August 2018 в 00:34
поделиться

Ниже вы можете найти решение для Swift3 и немного расширенного (помощник ориентации):

typealias GradientPoints = (startPoint: CGPoint, endPoint: CGPoint)

enum GradientOrientation {
  case topRightBottomLeft
  case topLeftBottomRight
  case horizontal
  case vertical

  var startPoint : CGPoint {
    return points.startPoint
  }

  var endPoint : CGPoint {
    return points.endPoint
  }

  var points : GradientPoints {
    get {
      switch(self) {
      case .topRightBottomLeft:
        return (CGPoint(x: 0.0,y: 1.0), CGPoint(x: 1.0,y: 0.0))
      case .topLeftBottomRight:
        return (CGPoint(x: 0.0,y: 0.0), CGPoint(x: 1,y: 1))
      case .horizontal:
        return (CGPoint(x: 0.0,y: 0.5), CGPoint(x: 1.0,y: 0.5))
      case .vertical:
        return (CGPoint(x: 0.0,y: 0.0), CGPoint(x: 0.0,y: 1.0))
      }
    }
  }
}

extension UIView {

  func applyGradient(withColours colours: [UIColor], locations: [NSNumber]? = nil) -> Void {
    let gradient = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.colors = colours.map { $0.cgColor }
    gradient.locations = locations
    self.layer.insertSublayer(gradient, at: 0)
  }

  func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) -> Void {
    let gradient = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.colors = colours.map { $0.cgColor }
    gradient.startPoint = orientation.startPoint
    gradient.endPoint = orientation.endPoint
    self.layer.insertSublayer(gradient, at: 0)
  }
}
9
ответ дан Zeb 16 August 2018 в 00:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: