почему UIButton не отображается с градиентом - PullRequest
0 голосов
/ 12 апреля 2020

Привет, я новичок в Swift и Xcode и только изучаю основы. Я программно добавил слой градиента, а затем добавил UIButton, используя основную раскадровку, и назначил ему выход, но затем, когда я запускаю код, слой градиента отображается, но кнопка показывает, однако, когда я удаляю слой градиента, то UIButton показывает. Прикрепленный снимок экрана показывает, что происходит, когда используются и градиент, и код, и будет прикреплено.

class ViewController: UIViewController {
    let layer = CAGradientLayer()

    @IBOutlet weak var pressMeButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        layer.frame = view.bounds
        layer.colors = [UIColor.white.cgColor, UIColor(red: 128/255, green: 206/255, blue: 255/255, alpha: 1).cgColor]
        layer.startPoint = CGPoint(x: 0, y: 0)
        layer.endPoint = CGPoint(x: 0, y: 0.4)
        view.layer.addSublayer(layer)

        pressMeButton.layer.cornerRadius = 25.0
        pressMeButton.layer.borderWidth = 0.8
        pressMeButton.layer.borderColor = UIColor.black.cgColor
        pressMeButton.setTitle("Press Me", for: .normal)
        pressMeButton.setTitleColor(.black, for: .normal)
    }
}

Код с раскадровкой, показывающий расположение кнопок и симулятор без кнопки:

screen snapshot

Ответы [ 3 ]

0 голосов
/ 13 апреля 2020

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

Лучшее решение - определить GradientView, подложка которого , продиктованный его layerClass, является CAGradientLayer. Таким образом (а) он всегда будет ниже кнопки; и (b) он автоматически адаптируется к frame изменениям (и делает это изящно более изящно во время анимаций, чем layoutSubviews или viewDidLayoutSubviews подходы тоже):

@IBDesignable
class GradientView: UIView {
    override class var layerClass: AnyClass { return CAGradientLayer.self }
    private var gradientLayer: CAGradientLayer { return layer as! CAGradientLayer }

    @IBInspectable var startColor: UIColor = .white { didSet { updateGradient() } }
    @IBInspectable var endColor:   UIColor = #colorLiteral(red: 0.5019607843, green: 0.8078431373, blue: 1, alpha: 1)     { didSet { updateGradient() } }
    @IBInspectable var startPoint: CGFloat = 0      { didSet { updateGradient() } }
    @IBInspectable var endPoint:   CGFloat = 0.4    { didSet { updateGradient() } }


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

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

private extension GradientView {
    func updateGradient() {
        gradientLayer.colors = [startColor, endColor].map { $0.cgColor }
        gradientLayer.startPoint = CGPoint(x: 0, y: startPoint)
        gradientLayer.endPoint = CGPoint(x: 0, y: endPoint)
    }
}

С этим @IBDesignable Затем вы можете установить базовый класс для представления вашего контроллера представления равным GradientView, и он будет отображаться под кнопкой и будет правильно отображаться в Интерфейсном Разработчике. Например, щелкните в фоновом режиме и go на вкладке «Identity Inspector» на самой правой панели и установите «Class» в разделе «Custom Class»:

enter image description here

Вы можете изменить начальные / конечные цвета и начальные / конечные точки прямо в IB, если хотите, выбрав панель «Инспектор атрибутов» справа:

enter image description here

Очевидно, что если вы поступите таким образом, вам вообще не придется играть со слоем вида в viewDidLoad. Но если вы хотите изменить это программно, вы можете сделать что-то вроде:

override func viewDidLoad() {
    super.viewDidLoad()

    if let view = view as? GradientView {
        view.startColor = .black
        view.endColor = .red
    }
}

Но я бы лично установил цвета (или что-то еще) прямо в IB. И я бы оставил весь код «View Configuration» в классе UIView, к которому он принадлежит, а не в контроллере View.

0 голосов
/ 15 апреля 2020

Спасибо за помощь, но в итоге я создал стакан с параметрами для градиента и еще один стакан с параметрами для определенных цветов, а затем смог перетащить их в viewLoad.

0 голосов
/ 12 апреля 2020

Вы добавляете слой поверх вида, в то время как вы добавили UIButton перед рукой. Таким образом, слой перекрывает UIButton.

Вам необходимо добавить вид контейнера в главном виде контроллера, а затем добавить слой градиента поверх него.

...