web-dev-qa-db-fra.com

Comment créer des boutons radio et des cases à cocher dans Swift (iOS)?

Je développe une application qui permet de faire une enquête. Ma mise en page est générée à partir de questions basées sur XML. 

J'ai besoin de créer des boutons radio (choix unique) et des cases à cocher (réponses multiples). Je n'ai rien trouvé d'utile pour Swift. 

Est-ce que quelqu'un a une idée?

53
Vannian

Pour les boutons radio et les cases à cocher, rien n’est intégré. 

Vous pouvez vous-même mettre en œuvre des cases à cocher facilement. Vous pouvez définir une image non cochée pour votre bouton pour UIControlStateNormal et une image vérifiée pour votre UIControlStateSelected. Maintenant, lorsque vous appuyez sur le bouton, son bouton change d’image et alterne les images cochées et les images non cochées. 

Pour utiliser les boutons radio, vous devez conserver une Array pour tous les boutons que vous souhaitez utiliser comme boutons radio. Chaque fois que vous appuyez sur un bouton, vous devez décocher tous les autres boutons du tableau. 

Pour les boutons radio, vous pouvez utiliser SSRadioButtonsController Vous pouvez créer un objet contrôleur et y ajouter un tableau de boutons comme 

var radioButtonController = SSRadioButtonsController()
radioButtonController.setButtonsArray([button1!,button2!,button3!])

Le principe de base est quelque chose comme ceci ici .

34
S Shahid

Case à cocher

Vous pouvez créer votre propre contrôle CheckBox en étendant UIButton avec Swift:

import UIKit

class CheckBox: UIButton {
    // Images
    let checkedImage = UIImage(named: "ic_check_box")! as UIImage
    let uncheckedImage = UIImage(named: "ic_check_box_outline_blank")! as UIImage

    // Bool property
    var isChecked: Bool = false {
        didSet{
            if isChecked == true {
                self.setImage(checkedImage, for: UIControlState.normal)
            } else {
                self.setImage(uncheckedImage, for: UIControlState.normal)
            }
        }
    }

    override func awakeFromNib() {
        self.addTarget(self, action:#selector(buttonClicked(sender:)), for: UIControlEvents.touchUpInside)
        self.isChecked = false
    }

    func buttonClicked(sender: UIButton) {
        if sender == self {
            isChecked = !isChecked
        }
    }
}

Et ajoutez-le à vos vues avec Interface Builder:

 enter image description here

Boutons Radio

Les boutons radio peuvent être résolus de la même manière.

Par exemple, la sélection de sexe classique Femme - Homme:

 enter image description here

import UIKit

class RadioButton: UIButton {
    var alternateButton:Array<RadioButton>?

    override func awakeFromNib() {
        self.layer.cornerRadius = 5
        self.layer.borderWidth = 2.0
        self.layer.masksToBounds = true
    }

    func unselectAlternateButtons(){
        if alternateButton != nil {
            self.isSelected = true

            for aButton:RadioButton in alternateButton! {
                aButton.isSelected = false
            }
        }else{
            toggleButton()
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        unselectAlternateButtons()
        super.touchesBegan(touches, with: event)
    }

    func toggleButton(){
        self.isSelected = !isSelected
    }

    override var isSelected: Bool {
        didSet {
            if isSelected {
                self.layer.borderColor = Color.turquoise.cgColor
            } else {
                self.layer.borderColor = Color.grey_99.cgColor
            }
        }
    }
}

Vous pouvez lancer vos boutons radio comme ceci:

    override func awakeFromNib() {
        self.view.layoutIfNeeded()

        womanRadioButton.selected = true
        manRadioButton.selected = false
    }

    override func viewDidLoad() {
        womanRadioButton?.alternateButton = [manRadioButton!]
        manRadioButton?.alternateButton = [womanRadioButton!]
    }

J'espère que ça aide.

111
crubio

Départ DLRadioButton . Vous pouvez ajouter et personnaliser des boutons radio directement à partir d'Interface Builder. Fonctionne également parfaitement avec Swift.

 Swift Radio Button for iOS

Update: la version 1.3.2 a ajouté des boutons carrés, améliorant également les performances.

Mise à jour: la version 1.4.4 a ajouté l'option de sélection multiple, peut également être utilisée comme case à cocher.

Update: la version 1.4.7 a ajouté le support du langage RTL.

21
David Liu

Il existe une très bonne bibliothèque que vous pouvez utiliser pour cela (vous pouvez l'utiliser à la place de UISwitch): https://github.com/Boris-Em/BEMCheckBox

La configuration est facile:

BEMCheckBox *myCheckBox = [[BEMCheckBox alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[self.view addSubview:myCheckBox];

Il propose des cases à cocher de type cercle et carré 

 enter image description here

Et il fait aussi des animations:

 enter image description here

8
Calvin Alvin

Un contrôle très simple de case à cocher.

 @IBAction func btn_box(sender: UIButton) {
    if (btn_box.selected == true)
    {
        btn_box.setBackgroundImage(UIImage(named: "box"), forState: UIControlState.Normal)

            btn_box.selected = false;
    }
    else
    {
        btn_box.setBackgroundImage(UIImage(named: "checkBox"), forState: UIControlState.Normal)

        btn_box.selected = true;
    }
}
3
Pragnesh Vitthani

Étapes pour créer un bouton radio

BasicStep: prenez Two Button. définir l'image à la fois comme sélectionnée et non sélectionnée . que d'ajouter une action à la fois le bouton . maintenant démarrer le code

1) Créer une variable: 

var btnTag    : Int = 0

2) Dans ViewDidLoad, définissez: 

 btnTag = btnSelected.tag

3) Maintenant dans l'action de tapotement sélectionnée:

 @IBAction func btnSelectedTapped(sender: AnyObject) {
    btnTag = 1
    if btnTag == 1 {
      btnSelected.setImage(UIImage(named: "icon_radioSelected"), forState: .Normal)
      btnUnSelected.setImage(UIImage(named: "icon_radioUnSelected"), forState: .Normal)
     btnTag = 0
    }
}

4) Code pour le bouton UnCheck

 @IBAction func btnUnSelectedTapped(sender: AnyObject) {
    btnTag = 1
    if btnTag == 1 {
        btnUnSelected.setImage(UIImage(named: "icon_radioSelected"), forState: .Normal)
        btnSelected.setImage(UIImage(named: "icon_radioUnSelected"), forState: .Normal)
        btnTag = 0
    }
}

Le bouton radio est prêt pour vous

2
Krutarth Patel

version plus courte de l'ios Swift 4:

@IBAction func checkBoxBtnTapped(_ sender: UIButton) {
        if checkBoxBtn.isSelected {
            checkBoxBtn.setBackgroundImage(#imageLiteral(resourceName: "ic_signup_unchecked"), for: .normal)
        } else {
            checkBoxBtn.setBackgroundImage(#imageLiteral(resourceName: "ic_signup_checked"), for:.normal)
        }
        checkBoxBtn.isSelected = !checkBoxBtn.isSelected
    }
2
Gulz

Pour une case à cocher, vous n'avez pas besoin de sous-classer le UIButton. Il a déjà la propriété isSelected pour gérer cela.

checkbox = UIButton.init(type: .custom)
checkbox.setImage(UIImage.init(named: "iconCheckboxOutlined"), for: .normal)
checkbox.setImage(UIImage.init(named: "iconCheckboxFilled"), for: .selected)
checkbox.addTarget(self, action: #selector(self.toggleCheckboxSelection), for: .touchUpInside)

Ensuite, dans la méthode d'action, basculez son état isSelected.

@objc func toggleCheckboxSelection() {
    checkbox.isSelected = !checkbox.isSelected
}
1
Salil Dhawan
  1. Créez 2 boutons, l'un sous la forme "OUI" et l'autre sous la forme "NON".
  2. Créer une propriété BOOL Ex: isNRICitizen = false
  3. Donnez la même connexion aux deux boutons et créez une étiquette
@IBAction func btnAction(_ sender:UIButton) {

isNRICitizen = sender.tag == 10 ? true : false
isNRICitizen ? self.nriCitizenBtnYes.setImage(#imageLiteral(resourceName: "radioChecked"), for: .normal) : self.nriCitizenBtnYes.setImage(#imageLiteral(resourceName: "radioUnchecked"), for: .normal)
        isNRICitizen ? self.nriCitizenBtnNo.setImage(#imageLiteral(resourceName: "radioUnchecked"), for: .normal) : self.nriCitizenBtnNo.setImage(#imageLiteral(resourceName: "radioChecked"), for: .normal)
}
0
Ravindra Kishan

La décision de cocher ou de décocher le bouton de la case à cocher sort du cadre de la vue. Voir lui-même ne devrait s'occuper que de dessiner les éléments, pas de décider de l'état interne de cela. Ma mise en œuvre suggérée est la suivante:

import UIKit

class Checkbox: UIButton {

    let checkedImage = UIImage(named: "checked")
    let uncheckedImage = UIImage(named: "uncheked")
    var action: ((Bool) -> Void)? = nil

    private(set) var isChecked: Bool = false {
        didSet{
            self.setImage(
                self.isChecked ? self.checkedImage : self.uncheckedImage,
                for: .normal
            )
        }
    }

    override func awakeFromNib() {
        self.addTarget(
            self,
            action:#selector(buttonClicked(sender:)),
            for: .touchUpInside
        )
        self.isChecked = false
    }

    @objc func buttonClicked(sender: UIButton) {
        if sender == self {
            self.action?(!self.isChecked)
        }
    }

    func update(checked: Bool) {
        self.isChecked = checked
    }
}

Il peut être utilisé avec Interface Builder ou par programme. L'utilisation de la vue pourrait être comme dans l'exemple suivant:

let checkbox_field = Checkbox(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
checkbox_field.action = { [weak checkbox_field] checked in
    // any further checks and business logic could be done here
    checkbox_field?.update(checked: checked)
}
0

Pour les cases à cocher, il existe une solution intégrée sous la forme d'accessoires UITableViewCell. Vous pouvez configurer votre formulaire en tant que UITableView dans lequel chaque cellule est une option sélectionnable et utiliser accessoryType pour définir une coche pour les éléments sélectionnés.

Voici un exemple de pseudo-code:

    let items = [SelectableItem]

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


        // Get the item for the current row
        let item = self.items[indexPath.row]

        // ...dequeue and set up the `cell` as you wish...

        // Use accessoryType property to mark the row as checked or not...
        cell.accessoryType = item.selected ? .checkmark : .none
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // Unselect row
        tableView.deselectRow(at: indexPath, animated: false)

        // Toggle selection
        let item = self.items[indexPath.row]
        item.selected = !item.selected
        tableView.reloadData()
    }

Les boutons radio nécessitent toutefois une implémentation personnalisée, voir les autres réponses.

0
Aron

Vous pouvez simplement sous-classer UIButton et écrire votre propre code de dessin pour répondre à vos besoins. J'ai implémenté un bouton radio comme celui de Android à l'aide du code suivant. Il peut également être utilisé dans le storyboard . Voir l'exemple dans le repo Github

import UIKit

@IBDesignable
class SPRadioButton: UIButton {

@IBInspectable
var gap:CGFloat = 8 {
    didSet {
        self.setNeedsDisplay()
    }
}

@IBInspectable
var btnColor: UIColor = UIColor.green{
    didSet{
        self.setNeedsDisplay()
    }
}

@IBInspectable
var isOn: Bool = true{
    didSet{
        self.setNeedsDisplay()
    }
}

override func draw(_ rect: CGRect) {
    self.contentMode = .scaleAspectFill
    drawCircles(rect: rect)
}


//MARK:- Draw inner and outer circles
func drawCircles(rect: CGRect){
    var path = UIBezierPath()
    path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: rect.width, height: rect.height))

    let circleLayer = CAShapeLayer()
    circleLayer.path = path.cgPath
    circleLayer.lineWidth = 3
    circleLayer.strokeColor = btnColor.cgColor
    circleLayer.fillColor = UIColor.white.cgColor
    layer.addSublayer(circleLayer)

    if isOn {
        let innerCircleLayer = CAShapeLayer()
        let rectForInnerCircle = CGRect(x: gap, y: gap, width: rect.width - 2 * gap, height: rect.height - 2 * gap)
        innerCircleLayer.path = UIBezierPath(ovalIn: rectForInnerCircle).cgPath
        innerCircleLayer.fillColor = btnColor.cgColor
        layer.addSublayer(innerCircleLayer)
    }
    self.layer.shouldRasterize =  true
    self.layer.rasterizationScale = UIScreen.main.nativeScale
}

/*
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    isOn = !isOn
    self.setNeedsDisplay()
}
*/    

override func awakeFromNib() {
    super.awakeFromNib()
    addTarget(self, action: #selector(buttonClicked(sender:)), for: UIControl.Event.touchUpInside)
    isOn = false
}

@objc func buttonClicked(sender: UIButton) {
    if sender == self {
        isOn = !isOn
        setNeedsDisplay()
    }
}
}
0
Nikesh Jha