Taylor
Taylor

Reputation: 23

How can I deselect all other buttons in array when one is selected?

Currently when I select a button in my array it will turn from gray to black and turn back to gray if selected again, which I want. The issue is when I select one button and select another they will both be black. How can I make it so when I select one button, then select another, the previous one will go back to gray?

let subjectArray = ["Button1", "Button2", "Button3", "Button4"]   
for title in subjectArrary {
                let button = UIButton()
                button.backgroundColor = UIColor.white
                button.setTitle("\(title)", for: .normal)
                button.setTitleColor(UIColor.gray, for: .normal)
                button.heightAnchor.constraint(equalToConstant: 60).isActive = true
                button.widthAnchor.constraint(equalToConstant: 140).isActive = true
                button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)

                stack.addArrangedSubview(button)
            }



    func buttonPressed(sender:AnyObject) {

            guard let button = sender as? UIButton else { return }

            if !button.isSelected {
                button.isSelected = true
                button.setTitleColor(UIColor.black, for: .normal)
            } else {
                button.isSelected = false
                button.setTitleColor(UIColor.gray, for: .normal)
            }
        }

Upvotes: 2

Views: 3377

Answers (6)

Kat
Kat

Reputation: 11

// Create an array of buttons which will hold all of your buttons
// This is a class property, we can already initialise this with empty array so we don't need to set it during class init()
let buttons: [UIButton] = [] 

func createButton(withTitle title: String) -> UIButton {
    let button = UIButton()
    button.setTitle(title, for: .normal)
    button.setTitleColor(.gray, for: .normal)
    button.setTitleColor(.black, for: .selected) // Please take note I've added this line
    button.backgroundColor = .white
    button.widthAnchor.constraint(equalToConstant: 140).isActive = true
    button.heightAnchor.constraint(equalToConstant: 60).isActive = true
    button.addTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside)
    return button
}

func setupButtons() {
    let subjectArray = ["Button1", "Button2", "Button3", "Button4"]   

    for title in subjectArrary {
        let button = createButton(withTitle: title)
        buttons.append(button) // Append all your buttons
        stack.addArrangedSubview(button)
    }
}

func didTapButton(_ button: UIButton) {
    deselectAllButtons()
    button.isSelected = !button.isSelected // set/unset of button state happens here
}

func deselectAllButtons() {
    buttons.forEach { $0.isSelected = false }
}

This line will set black title color to your button when it is selected..

button.setTitleColor(.black, for: .selected)

For a cleaner code, i've extracted the codes inside your for loop, made a small chunks of methods.. also, no need to add my code comments into your actual code ;)

Upvotes: 1

Bharath
Bharath

Reputation: 2114

If you want to reset the state of other buttons when new button is pressed then you could make use of the following code,

/**
 Reset the default state of the buttons
 */
func resetButtonStates() {
    for button in [YOUR_BUTTON_ARRAY_VARIABLE_HERE] {
        button.isSelected = false
        button.setTitleColor(UIColor.gray, for: .normal)
    }
}

func buttonPressed(sender:AnyObject) {
    guard let button = sender as? UIButton else { return }

    // Check wether the button is selected already, to be used as mentioned below
    let isAlreadySelected = sender.isSelected == true

    // Reset the default state to all the buttons
    resetButtonStates()

    // Now update the button state of the selected button alone if its not selected already
    if !isAlreadySelected {
        button.isSelected = true
        button.setTitleColor(UIColor.black, for: .normal)
    } else {
        // Do Nothing since as per your case if you selected the already selected button it should change to disable right, so the resetButtonStates() will do that.
    }
}

Upvotes: 0

rv7284
rv7284

Reputation: 1102

try creating an array of buttons

var buttonArray = [UIButton]()


func buttonPressed(sender:AnyObject) {
    let _ = buttonArray.map({$0.isSelected = false})
    sender.isSelected = true
}

this will do the trick

Upvotes: 0

NF Lee
NF Lee

Reputation: 482

when u creating buttons u can add them into a array such like

let bs = [UIButton]()    
for title in subjectArrary {
    let b = .......
    bs.append(b)
}

and in the action method

for b in bs {
    b.setTitleColor(.gray, for: .normal)
}
(sender as? UIButton).setTitleColor(.black, for: .normal)

Upvotes: 0

Woof
Woof

Reputation: 1443

If you have an outlet collection:

@IBOutlet var buttons: [UIButton]!

You can detect which is selected

func buttonPressed(sender:AnyObject) {

        guard let currentButton = sender as? UIButton else { return }

        buttons.forEach{ (element) in
                if element == currentButton {
                      //change state and params for current button
                }else{
                     //change other buttons
                }
        }
    }

Upvotes: 0

Nicolas Miari
Nicolas Miari

Reputation: 16256

Use NotificationCenter.

  1. Define a custom notification name.
  2. Subscribe all your buttons to listen to the notification using the method: NotificationCenter.default.addObserver(....
  3. In the control action method of your button class, post the notification with object (i.e., the sender of the notification) set to self.
  4. In the notification handler method registered with the notification, check for the notification's object property. If it is not equal to self, deselect the current button.

Upvotes: 0

Related Questions