I am making an app for learning Japanese for beginners. And there was a situation that I can not resolve. It is necessary for me that when choosing the level of complexity only one of three buttons can be active by choice (as we usually choose complexity).

When you choose the alphabet, it is possible that two buttons are active or one.

Maybe it's easy, but I'm new and just starting to figure it out. Thanks in advance for your answers.

buttons

    3 answers 3

    • You can style UISegmentedControl .
    • Inherit from UIControl and create your element
    • Add 3 buttons and when you click on one of them, the other two "press".
    • Use a third-party library that fits your needs.

      Option 1:

      Create a custom control with this button, create a logical property like isSelected . Add a collection of such controls to your ViewController, hang up the action to click. When clicking, put the desired isSelected status to the one you clicked on, then go through all the elements of the collection and check that they have the correct status. (because only one can be active)

      This option is quite beautifully solved through RxSwift + MVVM, but it will probably be difficult for a beginner.

      Option 2:

      Use UISegmentedControl .

      This control can only have one element a priori active, use the selectedSegmentIndex property. Poshaman a little with visual display, will be very similar to what you drew.

      An example of a solution to the forehead:

       class ViewController: UIViewController { @IBOutlet weak var buttonHiragana: UIButton! @IBOutlet weak var buttonKatagana: UIButton! @IBOutlet weak var buttonEasy: UIButton! @IBOutlet weak var buttonMedium: UIButton! @IBOutlet weak var buttonHard: UIButton! enum difficultyLevel { case Easy case Medium case Hard } var chosenDifficulty: difficultyLevel = .Easy; var isHiraganaChosen: Bool = true; var isKataganaChosen: Bool = true; override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. // Стартовые значения скорее всего будут грузится откуда-то из настроек // Сейчас мы их захардкодим self.buttonEasy.backgroundColor = UIColor.green; self.buttonMedium.backgroundColor = UIColor.white; self.buttonHard.backgroundColor = UIColor.white; self.buttonHiragana.backgroundColor = UIColor.green; self.buttonKatagana.backgroundColor = UIColor.green; } @IBAction func buttonHiraganaTapped(_ sender: UIButton) { if (isHiraganaChosen) { if (isKataganaChosen) { isHiraganaChosen = false; self.redrawSingleButton(isChosen: isHiraganaChosen, for: sender) } else { // Тут желательно как-то сообщить ползователю, что так нельзя делать // Можно использовать UIAlertView или что-то еще NSLog("Must have at least one alphabet chosen"); } } else { isHiraganaChosen = true; self.redrawSingleButton(isChosen: isHiraganaChosen, for: sender) } } @IBAction func buttonKataganaTapped(_ sender: UIButton) { if (isKataganaChosen) { if (isHiraganaChosen) { isKataganaChosen = false; self.redrawSingleButton(isChosen: isKataganaChosen, for: sender) } else { // Тут желательно как-то сообщить ползователю, что так нельзя делать // Можно использовать UIAlertView или что-то еще NSLog("Must have at least one alphabet chosen"); } } else { isKataganaChosen = true; self.redrawSingleButton(isChosen: isKataganaChosen, for: sender) } } @IBAction func buttonEasyTapped(_ sender: UIButton) { self.redrawDifficultyButtons(with: .Easy, and: sender); } @IBAction func buttonMediumTapped(_ sender: UIButton) { self.redrawDifficultyButtons(with: .Medium, and: sender) } @IBAction func buttonHardTapped(_ sender: UIButton) { self.redrawDifficultyButtons(with: .Hard, and: sender) } private func redrawSingleButton(isChosen: Bool, for button: UIButton) { if (isChosen) { button.backgroundColor = UIColor.green; } else { button.backgroundColor = UIColor.white; } } private func redrawDifficultyButtons(with difficulty: difficultyLevel, and button: UIButton) { // chosenDifficulty - сейчас старая сложность // difficulty - новая // oldButton - старая активная кнопка // button - новая let oldButton: UIButton; if (self.chosenDifficulty != difficulty) { if (self.chosenDifficulty == .Easy) { oldButton = buttonEasy; } else if (self.chosenDifficulty == .Medium) { oldButton = buttonMedium; } else { oldButton = buttonHard; } self.redrawSingleButton(isChosen: false, for: oldButton); self.redrawSingleButton(isChosen: true, for: button); self.chosenDifficulty = difficulty; } } } 
      • Can you show the solution through RxSwift, if not hard? I would be very grateful. - Ivan Kramarchuk 2:53 pm
      • The control segment is not suitable, since in the middle part of the question is described a variant in which the activity of two buttons is possible at once. - NSA-bot
      • With the help of UISegmentedControl, I can probably make only the choice of complexity. But the choice of the alphabet is no longer. - Igor Mokritskyi
      • So, what's the problem with the choice of the alphabet? There you do not need to check the status of other elections, it is much easier. - Olter
      • @IgorMokritskyi, added sample code - Olter

      Another solution is to use the RxSwift library.

      It turns out like this:

       import UIKit import RxCocoa import RxSwift class ReactiveViewController: UIViewController { @IBOutlet weak var buttonHiragana: UIButton! @IBOutlet weak var buttonKatagana: UIButton! @IBOutlet weak var buttonEasy: UIButton! @IBOutlet weak var buttonMedium: UIButton! @IBOutlet weak var buttonHard: UIButton! @IBOutlet weak var buttonNext: UIButton! enum difficultyLevel { case Easy case Medium case Hard } var chosenDifficulty: difficultyLevel = .Easy; // RxSwift objects fileprivate let disposeBag = DisposeBag() var isButtonHiraganaSelected:Variable = Variable(true) var isButtonKataganaSelected:Variable = Variable(true) override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.buttonEasy.backgroundColor = UIColor.green; self.buttonMedium.backgroundColor = UIColor.white; self.buttonHard.backgroundColor = UIColor.white; self.buttonHiragana.backgroundColor = UIColor.green; self.buttonKatagana.backgroundColor = UIColor.green; // RxSwift bindings buttonHiragana.rx.tap.bind { if (self.isButtonHiraganaSelected.value) { if (self.isButtonKataganaSelected.value) { self.isButtonHiraganaSelected.value = false; self.redrawSingleButton(isChosen: self.isButtonHiraganaSelected.value, for: self.buttonHiragana) } else { // Тут желательно как-то сообщить ползователю, что так нельзя делать // Можно использовать UIAlertView или что-то еще NSLog("Must have at least one alphabet chosen"); } } else { self.isButtonHiraganaSelected.value = true; self.redrawSingleButton(isChosen: self.isButtonHiraganaSelected.value, for: self.buttonHiragana) } }.disposed(by: disposeBag) buttonKatagana.rx.tap.bind { if (self.isButtonKataganaSelected.value) { if (self.isButtonHiraganaSelected.value) { self.isButtonKataganaSelected.value = false; self.redrawSingleButton(isChosen: self.isButtonKataganaSelected.value, for: self.buttonKatagana) } else { // Тут желательно как-то сообщить ползователю, что так нельзя делать // Можно использовать UIAlertView или что-то еще NSLog("Must have at least one alphabet chosen"); } } else { self.isButtonKataganaSelected.value = true; self.redrawSingleButton(isChosen: self.isButtonKataganaSelected.value, for: self.buttonKatagana) } }.disposed(by: disposeBag) buttonEasy.rx.tap.bind { self.redrawDifficultyButtons(with: .Easy, and: self.buttonEasy); }.disposed(by: disposeBag) buttonMedium.rx.tap.bind { self.redrawDifficultyButtons(with: .Medium, and: self.buttonMedium); }.disposed(by: disposeBag) buttonHard.rx.tap.bind { self.redrawDifficultyButtons(with: .Hard, and: self.buttonHard); }.disposed(by: disposeBag) } private func redrawSingleButton(isChosen: Bool, for button: UIButton) { if (isChosen) { button.backgroundColor = UIColor.green; } else { button.backgroundColor = UIColor.white; } } private func redrawDifficultyButtons(with difficulty: difficultyLevel, and button: UIButton) { // chosenDifficulty is old // difficulty is new let oldButton: UIButton; if (self.chosenDifficulty != difficulty) { if (self.chosenDifficulty == .Easy) { oldButton = buttonEasy; } else if (self.chosenDifficulty == .Medium) { oldButton = buttonMedium; } else { oldButton = buttonHard; } self.redrawSingleButton(isChosen: false, for: oldButton); self.redrawSingleButton(isChosen: true, for: button); self.chosenDifficulty = difficulty; } } 

      Usually RxSwift is used together with the MVVM architectural template, but I'm too lazy to select the ViewModel. Yes, you can also enter an additional Observable to go to the next screen, you will have something like:

       let everythingValid: Observable<Bool> = ЗамыканиеСУсловием everythingValid .bind(to: buttonNextScreen.rx.isEnabled) .disposed(by: disposeBag)