You can save yourself a lot of work by making use of the .normal
/ .highlighted
/ .disabled
states... and then overriding isEnabled
to handle the background color change:
class CustomButton: UIButton {
// these will be set by configure()
private var bkgEnabled: UIColor = .white
private var bkgDisabled: UIColor = .black
override init(frame: CGRect) {
super.init(frame: frame)
// configure with defaults
self.configure()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
// configure with defaults
self.configure()
}
// Format a button...
// Each parameter has a "default" value
func configure(titleNormal: UIColor? = .white,
titleHighlighted: UIColor? = .lightGray,
titleDisabled: UIColor? = .darkGray,
bkgEnabled: UIColor? = .red,
bkgDisabled: UIColor? = .lightGray) {
self.setTitleColor(titleNormal, for: .normal)
self.setTitleColor(titleHighlighted, for: .highlighted)
self.setTitleColor(titleDisabled, for: .disabled)
self.backgroundColor = self.isEnabled ? bkgEnabled : bkgDisabled
// update background color properties
self.bkgEnabled = bkgEnabled!
self.bkgDisabled = bkgDisabled!
}
// this will set the background color, based on Enabled / Disabled state
override var isEnabled: Bool {
didSet {
self.backgroundColor = isEnabled ? bkgEnabled : bkgDisabled
}
}
}
Here's an example controller... it will create two custom buttons:
- The top button - "button A" - will use the default color values
- we'll set custom color values for the bottom button - "button B"
- tapping the top button will toggle
.isEnabled
state of the bottom button
Controller class:
class ViewController: UIViewController {
let customButtonA = CustomButton()
let customButtonB = CustomButton()
override func viewDidLoad() {
super.viewDidLoad()
customButtonA.translatesAutoresizingMaskIntoConstraints = false
customButtonB.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(customButtonA)
view.addSubview(customButtonB)
NSLayoutConstraint.activate([
customButtonA.centerXAnchor.constraint(equalTo: view.centerXAnchor),
customButtonA.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -80.0),
customButtonB.centerXAnchor.constraint(equalTo: view.centerXAnchor),
customButtonB.topAnchor.constraint(equalTo: customButtonA.bottomAnchor, constant: 40.0),
])
customButtonA.setTitle("Toggle enabled/disabled", for: [])
customButtonB.setTitle("Enabled", for: [])
customButtonA.addTarget(self, action: #selector(btnATapped(_:)), for: .touchUpInside)
customButtonB.addTarget(self, action: #selector(btnBTapped(_:)), for: .touchUpInside)
customButtonB.configure(titleNormal: .red, titleHighlighted: .green, titleDisabled: .black, bkgEnabled: .yellow, bkgDisabled: .gray)
}
@objc func btnATapped(_ sender: UIButton) {
print("Toggling .isEnabled of button B")
customButtonB.isEnabled.toggle()
let t: String = customButtonA.isEnabled ? "Enabled" : "Disabled"
customButtonB.setTitle(t, for: [])
}
@objc func btnBTapped(_ sender: UIButton) {
print("Button B tapped")
}
}
class CustomButton: UIButton {
// these will be set by configure()
private var bkgEnabled: UIColor = .white
private var bkgDisabled: UIColor = .black
override init(frame: CGRect) {
super.init(frame: frame)
// configure with defaults
self.configure()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
// configure with defaults
self.configure()
}
// Format a button...
// Each parameter has a "default" value
func configure(titleNormal: UIColor? = .white,
titleHighlighted: UIColor? = .lightGray,
titleDisabled: UIColor? = .darkGray,
bkgEnabled: UIColor? = .red,
bkgDisabled: UIColor? = .lightGray) {
self.setTitleColor(titleNormal, for: .normal)
self.setTitleColor(titleHighlighted, for: .highlighted)
self.setTitleColor(titleDisabled, for: .disabled)
self.backgroundColor = self.isEnabled ? bkgEnabled : bkgDisabled
// update background color properties
self.bkgEnabled = bkgEnabled!
self.bkgDisabled = bkgDisabled!
}
// this will set the background color, based on Enabled / Disabled state
override var isEnabled: Bool {
didSet {
self.backgroundColor = isEnabled ? bkgEnabled : bkgDisabled
}
}
}
Looks like this to start:

while the bottom button is tapped (highlighted):

and after tapping the top button to disable the bottom button:
