Ich entwickle eine App, die eine Umfrage ermöglicht. Mein Layout wird aus XML-basierten Fragen generiert.
Ich muss Optionsfelder (einfache Auswahl) und Kontrollkästchen (mehrere Antworten) erstellen. Ich habe nichts Nützliches für Swift gefunden.
Hat jemand eine Idee?
Für Radio Buttons und CheckBoxes ist nichts eingebaut.
Sie können Checkboxen einfach selbst implementieren. Sie können für UIControlStateNormal ein uncheckedImage und für UIControlStateSelected ein checkedImage festlegen. Wenn Sie jetzt auf die Schaltfläche tippen, ändert sich die Schaltfläche und wechselt zwischen aktiviertem und ungeprüftem Bild.
Um Optionsfelder verwenden zu können, müssen Sie eine Array
für alle Tasten behalten, die Sie als Optionsfelder verwenden möchten. Immer wenn eine Taste gedrückt wird, müssen Sie alle anderen Tasten im Array deaktivieren.
Für Radiobuttons können Sie SSRadioButtonsController .__ verwenden. Sie können ein Controller-Objekt erstellen und Schaltflächen-Array hinzufügen
var radioButtonController = SSRadioButtonsController()
radioButtonController.setButtonsArray([button1!,button2!,button3!])
Das Hauptprinzip ist so etwas wie dies hier .
Checkbox
Sie können mit Swift ein eigenes CheckBox-Steuerelement erstellen, das UIButton erweitert:
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
}
}
}
Und fügen Sie es dann mit Interface Builder zu Ihren Ansichten hinzu:
Radio Knöpfe
Optionsfelder können auf ähnliche Weise gelöst werden.
Zum Beispiel die klassische Geschlechtsauswahl Frau - Mann:
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
}
}
}
}
Sie können Ihre Optionsfelder wie folgt auslösen:
override func awakeFromNib() {
self.view.layoutIfNeeded()
womanRadioButton.selected = true
manRadioButton.selected = false
}
override func viewDidLoad() {
womanRadioButton?.alternateButton = [manRadioButton!]
manRadioButton?.alternateButton = [womanRadioButton!]
}
Ich hoffe es hilft.
Check out DLRadioButton . Sie können Optionsfelder direkt aus dem Interface Builder hinzufügen und anpassen. Funktioniert auch perfekt mit Swift
.
Update: Version 1.3.2
fügte quadratische Schaltflächen hinzu und verbesserte die Leistung.
Update: Version 1.4.4
hinzugefügte Mehrfachauswahloption, kann auch als Kontrollkästchen verwendet werden.
Update: Version 1.4.7
hat Unterstützung für RTL-Sprachen hinzugefügt.
Es gibt eine wirklich großartige Bibliothek, die Sie dafür verwenden können (Sie können diese anstelle von UISwitch
verwenden): https://github.com/Boris-Em/BEMCheckBox
Das Setup ist einfach:
BEMCheckBox *myCheckBox = [[BEMCheckBox alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[self.view addSubview:myCheckBox];
Sie enthält Kontrollkästchen für den Typ Kreis und Quadrat
Und es gibt auch Animationen:
Ein sehr einfaches Kontrollkästchen.
@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;
}
}
Schritte zum Erstellen eines Optionsfelds
BasicStep: Take Two Button. Legen Sie das Bild für den ausgewählten und den nicht ausgewählten Bereich fest
1) Variable erstellen:
var btnTag : Int = 0
2) In ViewDidLoad definieren:
btnTag = btnSelected.tag
3) Jetzt in der ausgewählten Tap-Aktion:
@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 für UnCheck Button eingeben
@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
}
}
Radio Button ist für Sie bereit
kürzere Version von 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
}
Für ein Kontrollkästchen müssen Sie den UIButton nicht subklassifizieren. Es verfügt bereits über die isSelected
-Eigenschaft, um damit umzugehen.
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)
In der Aktionsmethode Toggle ist dann der Status isSelected
.
@objc func toggleCheckboxSelection() {
checkbox.isSelected = !checkbox.isSelected
}
@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)
}
Die Entscheidung, das Kontrollkästchen zu aktivieren oder zu deaktivieren, liegt außerhalb des Bereichs der Ansicht. View selbst sollte sich nur um das Zeichnen der Elemente kümmern und nicht um deren internen Zustand. Meine vorgeschlagene Implementierung lautet wie folgt:
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
}
}
Es kann mit Interface Builder oder programmgesteuert verwendet werden. Die Verwendung der Ansicht könnte wie folgt aussehen:
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)
}
Für Checkboxen gibt es eigentlich eine integrierte Lösung in Form von UITableViewCell-Zubehör. Sie können Ihr Formular als UITableView einrichten, in dem jede Zelle als auswählbare Option verwendet wird, und mit accessoryType
ein Häkchen für ausgewählte Elemente setzen.
Hier ist ein Pseudocode-Beispiel:
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()
}
Optionsfelder erfordern jedoch eine benutzerdefinierte Implementierung, siehe die anderen Antworten.
Sie können UIButton einfach in Unterklassen unterteilen und Ihren eigenen Zeichnungscode gemäß Ihren Anforderungen schreiben. Ich habe ein Optionsfeld wie das von Android mit dem folgenden Code implementiert. Es kann auch im Storyboard verwendet werden. Siehe Beispiel in Github Repo
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()
}
}
}