UIButton с угловым радиусом, тенью и фоном для состояния

Кажется, это сложная проблема, для которой я не могу найти решение.

Мне нужен UIButton с:

  1. закругленные углы,
  2. цвет фона для состояния,
  3. падающая тень.

Я могу добиться радиуса угла и цвета фона для подкласса состояния UIButton и установки параметров:

// The button is set to "type: Custom" in the interface builder.

// 1. rounded corners
self.layer.cornerRadius = 10.0

// 2. Color for state
self.backgroundColor = UIColor.orange // for state .normal
self.setBackgroundColor(color: UIColor.red, forState: .highlighted)

// 3. Add the shadow
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: 3)
self.layer.shadowOpacity = 0.3
self.layer.shadowRadius = 6.0
self.layer.masksToBounds = false


// I'm also using an extension to be able to set the background color
extension UIButton {
    func setBackgroundColor(color: UIColor, forState: UIControl.State) {        
        UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
        if let context = UIGraphicsGetCurrentContext() {
            context.setFillColor(color.cgColor)
            context.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
            let colorImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            self.setBackgroundImage(colorImage, for: forState)
        }
    }
}

Проблема:
После того, как кнопка отобразилась, она выглядит нормально, имеет желаемый цвет фона, закругленные углы и тень. Но при нажатии setBackgroundImage(image, for: forState) запускается и избавляется от радиуса, поэтому кнопка отображается в виде квадрата с нужным цветом и тенью.

Есть ли способ сохранить радиус при нажатии кнопки (.highlighted)?

Я попробовал решения из этот пост (например) но никто не считает setBackgroundImage(image, for: forState). не могу найти ничего работающего...


person Jorge Frias    schedule 26.02.2020    source источник
comment
Планируете ли вы установить фактическое фоновое изображение для своей кнопки? Или вы просто делаете это, потому что нет свойства по умолчанию backgroundColor для состояния?   -  person DonMag    schedule 27.02.2020
comment
Как вы говорите, ваш ответ идеально соответствует моим потребностям.   -  person Jorge Frias    schedule 27.02.2020


Ответы (1)


Если вы просто хотите изменить цвет фона для .normal и .highlighted, то есть вам не нужно фоновое изображение, вы можете переопределить var isHighlighted для обработки изменений цвета.

Вот пример подкласса UIButton. Он помечен @IBDesignable и имеет цвета normalBackground и highlightBackground, помеченные как @IBInspectable, поэтому вы можете установить их в Storyboard / Interface Builder:

@IBDesignable
class HighlightButton: UIButton {

    @IBInspectable
    var normalBackground: UIColor = .clear {
        didSet {
            backgroundColor = self.normalBackground
        }
    }

    @IBInspectable
    var highlightBackground: UIColor = .clear

    override open var isHighlighted: Bool {
        didSet {
            backgroundColor = isHighlighted ? highlightBackground : normalBackground
        }
    }

    func setBackgroundColor(_ c: UIColor, forState: UIControl.State) -> Void {
        if forState == UIControl.State.normal {
            normalBackground = c
        } else if forState == UIControl.State.highlighted {
            highlightBackground = c
        } else {
            // implement other states as desired
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

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

    func commonInit() -> Void {

        // 1. rounded corners
        self.layer.cornerRadius = 10.0

        // 2. Default Colors for state
        self.setBackgroundColor(.orange, forState: .normal)
        self.setBackgroundColor(.red, forState: .highlighted)

        // 3. Add the shadow
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOffset = CGSize(width: 0, height: 3)
        self.layer.shadowOpacity = 0.3
        self.layer.shadowRadius = 6.0
        self.layer.masksToBounds = false

    }

}
person DonMag    schedule 26.02.2020