Изменение UIButton borderColor в синхронизации с заголовком при выделении - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть пользовательский UIButton с рамкой. Я бы хотел, чтобы layer.borderColor синхронизировался с titleLabel, когда кнопка реагирует на пользовательские события - то есть становится выделенным или выбранным .

Иногда эти события анимируются с задержкой, иногда сразу.

т.д .: Нажмите и удерживайте кнопку - немедленно Отпустите кнопку - с анимацией

Как заставить границу кнопки повторять то же поведение? Как отследить переходы между UIControlStates ?

т.е. Решение о том, нужно ли анимировать границу, зависит от перехода: Normal -> Highlighted - без анимации Highlighted -> Normal - с анимацией

Как я могу обнаружить такие переходы?

Вот код для кнопки, которая не обращается к событию перемещения пальца за пределы, но в остальном работает хорошо:

import UIKit

final class BorderButton: UIButton {
  override var isEnabled: Bool {
    didSet {
      updateBorderColor()
    }
  }

  override var isSelected: Bool {
    didSet {
      updateBorderColor(animated: false)
    }
  }

  override var isHighlighted: Bool {
    didSet {
      let animated = !isHighlighted
      updateBorderColor(animated: animated)
    }
  }

  override func tintColorDidChange() {
    super.tintColorDidChange()
    updateBorderColor()
  }

  private func updateBorderColor(animated: Bool = false) {
    var color: UIColor = tintColor
    if !isEnabled || tintAdjustmentMode == .dimmed {
      color = dimmedTintColor()
    } else if isHighlighted {
      color = lightColor()
    }

    if animated {
      let current = layer.borderColor ?? UIColor.clear.cgColor
      let cgColor = color.cgColor
      borderColorAnimation(from: current, to: cgColor, duration: 0.4)
    } else {
      layer.borderColor = color.cgColor
    }
  }


  private func borderColorAnimation(from: CGColor, to: CGColor, duration: CFTimeInterval) {
    let animation = CABasicAnimation(keyPath: "borderColor")
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    animation.fromValue = from
    animation.toValue = to
    animation.duration = duration
    layer.add(animation, forKey: "borderColor")
    layer.borderColor = to
  }

  private func lightColor() -> UIColor {
    var hue: CGFloat = 0, saturation: CGFloat = 0, brightness: CGFloat = 0, alpha: CGFloat = 0
    tintColor.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
    return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha * 0.2)
  }

  private func dimmedTintColor() -> UIColor {
    var hue: CGFloat = 0, brightness: CGFloat = 0, alpha: CGFloat = 0
    tintColor.getHue(&hue, saturation: nil, brightness: &brightness, alpha: &alpha)
    return UIColor(hue: hue, saturation: 0, brightness: brightness, alpha: alpha)
  }
}
...