I am trying to use two buttons to toggle between an animated sliding view. When the UIView loads, I want button1 to be UIColor.darkGrey and button2 to be UIColor.lightGrey. Then, when I press button2 I want button2 to become UIColor.darkGrey and button1 to become UIColor.lightGrey. If I press button1, I want button1 to be UIColor.darkGrey and button2 to be UIColor.lightGrey.
It seems simple; Using the storyboard, I connected a UIButton for button1 and button2 as an outlet. Then I connected each as actions. In each of the actions, I included the following code:
@IBAction func button1Action(_ sender: UIButton) {
button2.titleLabel?.textColor = UIColor.lightGray
button1.titleLabel?.textColor = UIColor.darkGray
UIView.animate(withDuration: 1){
self.side1.constant = 0
self.side2.constant = 0
self.sideA.constant = 400
self.sideB.constant = -400
self.view.layoutIfNeeded()
}
}
@IBAction func button2Action(_ sender: UIButton) {
button1.titleLabel?.textColor = UIColor.lightGray
button2.titleLabel?.textColor = UIColor.darkGray
view.layoutIfNeeded()
UIView.animate(withDuration: 1){
self.side1.constant = -400
self.side2.constant = 400
self.sideA.constant = 0
self.sideB.constant = 0
self.view.layoutIfNeeded()
}
}
When I press button1, everything works as expected; However, whenever I press button2 both buttons are UIColor.lightGrey. Am I missing something obvious?
You get some methods "for free" with buttons to manage their state. One of them is isSelected
. Another is the tag
property, so you can figure out which button is which. Since you've only got two buttons, you can get away with just using isSelected
to figure out which is which. You can also use computed vars
to make your life easier. With those things in mind, here's one approach you could utilize to managing the buttons' states:
Declare a buttons
computed var, like so
@IBOutlet var firstButton: UIButton!
@IBOutlet var secondButton: UIButton!
// computed var to access your buttons
private var buttons: [UIButton] {
return [firstButton, secondButton]
}
Set up your buttons in viewDidLoad
.
override func viewDidLoad() {
super.viewDidLoad()
// one setup to configure each button for selected or not selected
buttons.forEach { button in
button.setTitleColor(.darkGray,
for: .selected)
button.setTitleColor(.lightGray,
for: .normal)
}
firstButton.isSelected = true
}
func setTitleColor(_ color: UIColor?, for state: UIControl.State)
will remain in effect for the lifetime of the button, so you don't need to fiddle with it after the initial declaration (unless you want to change the button's behavior later).
One @IBAction
for both buttons and utilize the tag
property to figure out which one is which. Since you've only got two buttons, I'm just using isSelected
. Here's what your single @IBAction
would look like:
@IBAction func buttonAction(_ sender: UIButton) {
UIView.animate(withDuration: 1.0) {
// flip buttons
self.buttons.forEach { button in
button.isSelected.toggle()
}
if self.firstButton.isSelected {
// tweak your constraints for firstButton.isSelected == true
// tweak your constraints for secondButton.isSelected == false
} else {
// tweak your constraints for firstButton.isSelected == false
// tweak your constraints for secondButton.isSelected == true
}
}
}
Based on your current implementation, you'll need to right click on the UIButtons
on storyboard and nuke the existing IBAction
connections and reconnect both buttons to the method above.