Tworzę aplikację, która umożliwia przeprowadzanie ankiet. Mój układ jest generowany z pytań opartych na XML.
Muszę utworzyć przyciski opcji (pojedynczy wybór) i pola wyboru (wiele odpowiedzi). Nie znalazłem nic przydatnego dla szybkiego.
Czy ktoś ma pomysł?
Odpowiedzi:
W przypadku przycisków radiowych i pól wyboru nie ma nic wbudowanego.
Możesz łatwo wdrożyć Checkboxy samodzielnie. Możesz ustawić niezaznaczony obraz dla swojego przycisku dla UIControlStateNormal i checkImage dla swojego UIControlStateSelected. Teraz po dotknięciu przycisk zmieni swój obraz i będzie przełączał się między obrazem zaznaczonym i niezaznaczonym.
Aby użyć przycisków opcji, musisz zachować
Array
dla wszystkich przycisków, które mają zachowywać się jak przyciski opcji. Za każdym razem, gdy przycisk jest naciśnięty, należy odznaczyć wszystkie inne przyciski w tablicy.Dla przycisków radiowych możesz użyć SSRadioButtonsController Możesz stworzyć obiekt kontrolera i dodać do niego tablicę przycisków jak
var radioButtonController = SSRadioButtonsController() radioButtonController.setButtonsArray([button1!,button2!,button3!])
Główna zasada jest podobna do tego .
źródło
Pole wyboru
Możesz stworzyć własną kontrolkę CheckBox rozszerzającą UIButton za pomocą 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: UIControl.State.normal) } else { self.setImage(uncheckedImage, for: UIControl.State.normal) } } } override func awakeFromNib() { self.addTarget(self, action:#selector(buttonClicked(sender:)), for: UIControl.Event.touchUpInside) self.isChecked = false } @objc func buttonClicked(sender: UIButton) { if sender == self { isChecked = !isChecked } } }
Następnie dodaj go do swoich widoków za pomocą Interface Builder:
Przyciski radiowe
Przyciski radiowe można rozwiązać w podobny sposób.
Na przykład klasyczny wybór płci Kobieta - Mężczyzna :
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 } } } }
Możesz zainicjować swoje przyciski radiowe w ten sposób:
override func awakeFromNib() { self.view.layoutIfNeeded() womanRadioButton.selected = true manRadioButton.selected = false } override func viewDidLoad() { womanRadioButton?.alternateButton = [manRadioButton!] manRadioButton?.alternateButton = [womanRadioButton!] }
Mam nadzieję, że to pomoże.
źródło
Sprawdź DLRadioButton . Możesz dodawać i dostosowywać przyciski opcji bezpośrednio z programu Interface Builder. Działa również
Swift
doskonale z .Aktualizacja: wersja
1.3.2
dodała kwadratowe przyciski, również poprawiona wydajność.Aktualizacja: wersja
1.4.4
dodała opcję wielokrotnego wyboru, może być również używana jako pole wyboru.Aktualizacja: wersja
1.4.7
dodała obsługę języka RTL.źródło
multipleSelectionEnabled
iiconSquare
doYES
.Swift 5, pole wyboru z animacją
Utwórz wylot przycisku
@IBOutlet weak var checkBoxOutlet:UIButton!{ didSet{ checkBoxOutlet.setImage(UIImage(named:"unchecked"), for: .normal) checkBoxOutlet.setImage(UIImage(named:"checked"), for: .selected) } }
Utwórz rozszerzenie UIButton
extension UIButton { //MARK:- Animate check mark func checkboxAnimation(closure: @escaping () -> Void){ guard let image = self.imageView else {return} UIView.animate(withDuration: 0.1, delay: 0.1, options: .curveLinear, animations: { image.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) }) { (success) in UIView.animate(withDuration: 0.1, delay: 0, options: .curveLinear, animations: { self.isSelected = !self.isSelected //to-do closure() image.transform = .identity }, completion: nil) } } }
Jak używać
@IBAction func checkbox(_ sender: UIButton){ sender.checkboxAnimation { print("I'm done") //here you can also track the Checked, UnChecked state with sender.isSelected print(sender.isSelected) } }
Sprawdź mój przykład dla pola wyboru i przycisku radiowego https://github.com/rashidlatif55/CheckBoxAndRadioButton
źródło
didSet
checkBoxOutlet.layer.cornerRadius = checkBoxOutlet.frame.height / 2
usunąć niebieski,tint
gdy przycisk jest wybrany, możesz dodać tę linię jako rozszerzenieself.adjustsImageWhenHighlighted = false self.isHighlighted = false
Istnieje naprawdę świetna biblioteka, której możesz do tego użyć (możesz jej użyć zamiast
UISwitch
): https://github.com/Boris-Em/BEMCheckBoxKonfiguracja jest łatwa:
BEMCheckBox *myCheckBox = [[BEMCheckBox alloc] initWithFrame:CGRectMake(0, 0, 50, 50)]; [self.view addSubview:myCheckBox];
Zawiera pola wyboru typu koło i kwadrat
A także animacje:
źródło
Bardzo prosta kontrola pola wyboru.
@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; } }
źródło
krótsza wersja 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 }
źródło
Rozwiązanie dla przycisku radiowego w Swift 4.2 bez korzystania z bibliotek innych firm
Utwórz plik RadioButtonController.swift i umieść w nim następujący kod:
import UIKit class RadioButtonController: NSObject { var buttonsArray: [UIButton]! { didSet { for b in buttonsArray { b.setImage(UIImage(named: "radio_off"), for: .normal) b.setImage(UIImage(named: "radio_on"), for: .selected) } } } var selectedButton: UIButton? var defaultButton: UIButton = UIButton() { didSet { buttonArrayUpdated(buttonSelected: self.defaultButton) } } func buttonArrayUpdated(buttonSelected: UIButton) { for b in buttonsArray { if b == buttonSelected { selectedButton = b b.isSelected = true } else { b.isSelected = false } } } }
Użyj go jak poniżej w pliku kontrolera widoku:
import UIKit class CheckoutVC: UIViewController { @IBOutlet weak var btnPaytm: UIButton! @IBOutlet weak var btnOnline: UIButton! @IBOutlet weak var btnCOD: UIButton! let radioController: RadioButtonController = RadioButtonController() override func viewDidLoad() { super.viewDidLoad() radioController.buttonsArray = [btnPaytm,btnCOD,btnOnline] radioController.defaultButton = btnPaytm } @IBAction func btnPaytmAction(_ sender: UIButton) { radioController.buttonArrayUpdated(buttonSelected: sender) } @IBAction func btnOnlineAction(_ sender: UIButton) { radioController.buttonArrayUpdated(buttonSelected: sender) } @IBAction func btnCodAction(_ sender: UIButton) { radioController.buttonArrayUpdated(buttonSelected: sender) } }
Pamiętaj, aby dodać obrazy radio_off i radio_on w Zasobach.
Wynik:
źródło
RadioButtonController
instancją sprawdziłem tag wselectedButton
celu rozróżnienia, co zostało wybrane. Dzięki!Kroki tworzenia przycisku radiowego
BasicStep: weź dwa przyciski. ustaw obraz zarówno dla zaznaczonych, jak i niezaznaczonych. niż dodać akcję do obu przycisków. teraz uruchom kod
1) Utwórz zmienną:
var btnTag : Int = 0
2) W ViewDidLoad Define:
3) Teraz w wybranej akcji dotknięcia:
@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) Zrób kod dla przycisku 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 } }
Przycisk radiowy jest gotowy dla Ciebie
źródło
W przypadku pola wyboru nie musisz tworzyć podklasy UIButton. Ma już
isSelected
właściwość do obsługi tego.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)
Następnie w metodzie akcji przełącz jej
isSelected
stan.@objc func toggleCheckboxSelection() { checkbox.isSelected = !checkbox.isSelected }
źródło
Możesz po prostu utworzyć podklasę UIButton i napisać własny kod rysowania dostosowany do swoich potrzeb. Zaimplementowałem przycisk opcji, taki jak w Androidzie, używając następującego kodu. Może być również używany w scenorysie. Zobacz przykład w repozytorium 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() } } }
źródło
Stworzyłem super prostą klasę do obsługi tego w aplikacji na Maca, nad którą pracuję. Miejmy nadzieję, że to komuś pomoże
Klasa RadioButtonController:
class RadioButtonController: NSObject { var buttonArray : [NSButton] = [] var currentleySelectedButton : NSButton? var defaultButton : NSButton = NSButton() { didSet { buttonArrayUpdated(buttonSelected: self.defaultButton) } } func buttonArrayUpdated(buttonSelected : NSButton) { for button in buttonArray { if button == buttonSelected { currentleySelectedButton = button button.state = .on } else { button.state = .off } } }
}
Implementacja w kontrolerze widoku:
class OnboardingDefaultLaunchConfiguration: NSViewController { let radioButtonController : RadioButtonController = RadioButtonController() @IBOutlet weak var firstRadioButton: NSButton! @IBOutlet weak var secondRadioButton: NSButton! @IBAction func folderRadioButtonSelected(_ sender: Any) { radioButtonController.buttonArrayUpdated(buttonSelected: folderGroupRadioButton) } @IBAction func fileListRadioButtonSelected(_ sender: Any) { radioButtonController.buttonArrayUpdated(buttonSelected: fileListRadioButton) } override func viewDidLoad() { super.viewDidLoad() radioButtonController.buttonArray = [firstRadioButton, secondRadioButton] radioButtonController.defaultButton = firstRadioButton } }
źródło
@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) }
źródło
W przypadku checkboxów istnieje faktycznie wbudowane rozwiązanie w postaci akcesoriów UITableViewCell. Możesz skonfigurować swój formularz jako UITableView, w którym każda komórka jest opcją do wyboru i użyj
accessoryType
do ustawienia znacznika wyboru dla wybranych elementów.Oto przykład pseudokodu:
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() }
Jednak przyciski opcji wymagają niestandardowej implementacji, zobacz inne odpowiedzi.
źródło
Decyzja o zaznaczeniu lub odznaczeniu przycisku wyboru jest czymś poza zakresem widoku. Sam widok powinien zajmować się jedynie rysowaniem elementów, nie decydując o tym, jaki jest stan wewnętrzny. Moja sugerowana implementacja jest następująca:
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 } }
Może być używany z Interface Builder lub programowo. Użycie widoku może wyglądać następująco:
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) }
źródło
Swift 5.0 Zaktualizowany prosty RadioButton dla Swift (bez biblioteki)
Najpierw ustaw obrazy jako przycisk jeden zaznaczony, a drugi odznaczony.
Następnie zapewnij 2 gniazda z RadioButton.
@IBOutlet weak var radioMale: UIButton! @IBOutlet weak var radioFemale: UIButton!
Utwórz IBAction z obiema akcjami przycisku w jednej metodzie.
@IBAction func btnRadioTapped(_ sender: UIButton) { radioMale.setImage(UIImage(named: "Unchecked"), for: .normal) radioFemale.setImage(UIImage(named: "Unchecked"), for: .normal) if sender.currentImage == UIImage(named: "Unchecked"){ sender.setImage(UIImage(named: "Checked"), for: .normal) }else{ sender.setImage(UIImage(named: "Unchecked"), for: .normal) } }
źródło
Nie mam wystarczającej reputacji, aby komentować, więc zostawię tutaj swoją wersję wersji Salila Dwahan . Działa dla Swift 5, XCode 11.3.
Najpierw umieść przycisk na IB, wybierz typ „Niestandardowy” i utwórz punkt sprzedaży oraz akcję z układem asystenta (Ctrl + Przeciągnij). Uwzględnij następujący kod i powinien kończyć się tak:
class YourViewController: UIViewController { @IBOutlet weak var checkbox: UIButton! @IBAction func checkboxTapped(_ sender: UIButton) { checkbox.isSelected = !checkbox.isSelected } override func viewDidLoad() { super.viewDidLoad() checkbox.setImage(UIImage.init(named: "checkMark"), for: .selected) } }
Nie zapomnij dodać obrazu do zasobów i zmienić nazwę, aby pasowała!
checkbox.isSelected
to sposób na sprawdzenieźródło
Chociaż niektóre odpowiedzi słusznie wspominają o tym, że możemy użyć Selected State do ustawienia obrazu dla wybranego stanu przycisku, nie będzie to działać elegancko, gdy przycisk musi mieć zarówno obraz, jak i tekst.
Jak wielu, zakończyłem podklasą UIButton; jednak dodano obsługę ustawiania obrazów z Interface Builder.
Poniżej mój kod:
import UIKit class CustomCheckbox: UIButton { @IBInspectable var defaultStateImage: UIImage? = nil { didSet{ self.setNeedsDisplay() } } @IBInspectable var selectedStateImage: UIImage? = nil { didSet{ self.setNeedsDisplay() } } @IBInspectable var gapPadding: CGFloat = 0 { didSet{ self.setNeedsDisplay() } } @IBInspectable var isChecked: Bool = false { didSet{ self.setNeedsDisplay() } } var defaultImageView: UIImageView? = nil var selectedImageView: UIImageView? = nil override init(frame: CGRect) { super.init(frame: frame) setup() } required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } override func layoutSubviews() { super.layoutSubviews() setup() } func setup() { if(defaultStateImage != nil) { defaultImageView = UIImageView(image: defaultStateImage) defaultImageView?.translatesAutoresizingMaskIntoConstraints = false addSubview(defaultImageView!) let length = CGFloat(16) titleEdgeInsets.left += length NSLayoutConstraint.activate([ defaultImageView!.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: -gapPadding), defaultImageView!.centerYAnchor.constraint(equalTo: self.titleLabel!.centerYAnchor, constant: 0), defaultImageView!.widthAnchor.constraint(equalToConstant: length), defaultImageView!.heightAnchor.constraint(equalToConstant: length) ]) } if(selectedStateImage != nil) { selectedImageView = UIImageView(image: selectedStateImage) selectedImageView!.translatesAutoresizingMaskIntoConstraints = false addSubview(selectedImageView!) let length = CGFloat(16) titleEdgeInsets.left += length NSLayoutConstraint.activate([ selectedImageView!.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: -gapPadding), selectedImageView!.centerYAnchor.constraint(equalTo: self.titleLabel!.centerYAnchor, constant: 0), selectedImageView!.widthAnchor.constraint(equalToConstant: length), selectedImageView!.heightAnchor.constraint(equalToConstant: length) ]) } if defaultImageView != nil { defaultImageView!.isHidden = isChecked } if selectedImageView != nil { selectedImageView!.isHidden = !isChecked } self.addTarget(self, action: #selector(checkChanged(_:)), for: .touchUpInside) } @objc func checkChanged(_ btn : UIButton){ self.isChecked = !self.isChecked if defaultImageView != nil { defaultImageView!.isHidden = isChecked } if selectedImageView != nil { selectedImageView!.isHidden = !isChecked } } }
źródło