简体   繁体   中英

how to create radio buttons dynamically in swift?

I have the following buttons which are adding dynamically based on some condition. Now i need to change all added buttons behaviour as radio buttons. so that I can do some actions based on the selection..

  var posX = 0
    var posY = 0

    if trim.contains("0"){
        print("contaim 0")
        let button1 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
        button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
        button1.setTitle("No", forState: .Normal)
        button1.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
        button1.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
        myStackview.addSubview(button1)
        posX = 60
    }
    if trim.contains("1") {
        print("contaim 1")

        let button2 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
            button2.setTitleColor(UIColor.blackColor(), forState: .Normal)
            button2.setTitle("Less", forState: .Normal)
            button2.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
            button2.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
            myStackview.addSubview(button2)
            posX = posX + 60

    }
    if trim.contains("2"){
        print("contaim 2")

        let button3 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
        button3.setTitleColor(UIColor.blackColor(), forState: .Normal)

        button3.setTitle("Half", forState: .Normal)
        button3.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
        button3.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
        myStackview.addSubview(button3)
        posX =  posX + 60
    }

I have set the buttonAction methods as below buts its not working

func buttonAction(sender: UIButton!) {
    print("Button tapped")
    sender.setImage(UIImage(named: "checkboxredtick.png")!, forState: .Normal)

}
let buttons = [UIButton]()
// create button1
let button1 = UIButton(frame: CGRect(x: posX, y: posY, width: 60, height: 20))
button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
button1.setTitle("No", forState: .Normal)
button1.setImage(UIImage(named: "checkbox untick.png")!, forState: .Normal)
// if the selected button cannot be reclick again, you can use .Disabled state
button1.setImage(UIImage(named: "checkboxredtick.png")!, forState: .Selected)
button1.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)
myStackview.addSubview(button1)
buttons.append(button1)
// create other buttons and add into buttons ...

func buttonAction(sender: UIButton!){
    for button in buttons {
        button.selected = false
    }
    sender.selected = true
    // you may need to know which button to trigger some action
    // let buttonIndex = buttons.indexOf(sender)
}

In case anyone finds this useful. Here is an example of how I use DLRadioButton library ( https://github.com/DavydLiu/DLRadioButton ) to create RadioButtons dynamically. You can check a complete small project to show a working code in here https://github.com/omhack/DynamicRadioButtons

import UIKit
import DLRadioButton

//Delegate to manage the Polls
protocol QuestionsDialogDelegate : class{
    func questionsAnswered(polls: [Poll])
}

class QuestionsDialog: UIViewController {

    @IBOutlet weak var stackView: UIStackView!
    @IBOutlet var rootView: UIView!
    @IBOutlet weak var nestedView: UIView!
    weak var delegate: QuestionsDialogDelegate?
    var questions : [Question]!
    var polls = [Poll]()
    var serviceType : Int = 0
    var indexView : Int = 0


    override func viewDidLoad() {
        super.viewDidLoad()
        //setting the stack view properties
        stackView.alignment = UIStackViewAlignment.leading
        stackView.axis = .vertical

    }

    //this is where the heavy logic, to create the dynamic radio buttons takes place
    func showQuestions(){

        if(questions.count <= 1){
            rootView.frame.size.height = 200
            nestedView.frame.size.height = 200
        }else{
            rootView.frame.size.height = 400
            nestedView.frame.size.height = 400
        }

        for question in questions{
            var otherButtons : [DLRadioButton] = []

            let frame1 = CGRect(x: self.view.frame.size.width / 2 - 131, y: 350, width: 262, height: 17);
            //we create a base radio button to use it as an anchor view
            let firstRadioButton = createRadioButton(frame: frame1, title: "", color: UIColor.purple);

            let label = UILabel()
            label.textAlignment = .center
            label.font = UIFont.boldSystemFont(ofSize: 17.0)
            label.textColor = UIColor.darkGray.withAlphaComponent(0.85)
            label.adjustsFontSizeToFitWidth = true
            label.minimumScaleFactor = 0.25
            label.frame = CGRect(x: 0, y: 0, width: 200, height: 30)
            label.text = question.question

            self.stackView.insertArrangedSubview(label, at: self.indexView)

            self.indexView += 1
            let poll = Poll()
            poll.idQuestion = question.idQuestion

            var i = 0;
            for answer in question.answers{

                let frame = CGRect(x: self.view.frame.size.width / 2 - 131, y: 380 + 30 * CGFloat(i), width: 300, height: 17);
                let radioButton = createRadioButton(frame: frame, title: answer.answer! + " ", color: UIColor.purple)
                radioButton.tag = answer.idAnswer
                radioButton.params["poll"] = poll
                otherButtons.append(radioButton)
                self.stackView.insertArrangedSubview(radioButton, at: self.indexView)
                i += 1;
                self.indexView += 1
            }


            firstRadioButton.otherButtons = otherButtons
            firstRadioButton.isHidden = true
            firstRadioButton.otherButtons[1].isSelected = true

        }
    }

    //Method to create a custom button
    private func createRadioButton(frame : CGRect, title : String, color : UIColor) -> MyDLUIButton {
        let radioButton = MyDLUIButton(frame: frame);
        radioButton.titleLabel?.translatesAutoresizingMaskIntoConstraints = false
        radioButton.titleLabel!.font = UIFont.systemFont(ofSize: 14);
        radioButton.setTitle(title, for: []);
        radioButton.setTitleColor(UIColor.darkGray, for: []);
        radioButton.iconColor = color;
        radioButton.indicatorColor = color;
        radioButton.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left;
        radioButton.addTarget(self, action: #selector(QuestionsDialog.selectedAnswer(_:)), for: UIControlEvents.touchUpInside)
        self.view.addSubview(radioButton);

        return radioButton;
    }


    @objc func selectedAnswer(_ sender: MyDLUIButton){

        let poll = sender.params["poll"] as? Poll
        poll?.idAnswer = sender.tag


        if let row = self.polls.index(where: {$0.idQuestion == poll?.idQuestion}) {
            self.polls[row] = poll!
        }else{
            self.polls.append(poll!)
        }


        print("polls size: \(self.polls.count)")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func viewDidDisappear(_ animated: Bool) {
        if(self.polls.count < self.questions.count){
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "questionsDialogDismissed"), object: nil)
        }
    }

    @IBAction func requestService(_ sender: UIButton) {
        delegate?.questionsAnswered(polls: self.polls)
    }

}

class  MyDLUIButton: DLRadioButton{
    var params: Dictionary<String, Any>
    override init(frame: CGRect) {
        self.params = [:]
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        self.params = [:]
        super.init(coder: aDecoder)
    }
}

I would create a tag for every UIButton, then add your UIButton to be send to your ButtonAction:

button.tag = 0
button.addTarget(object, action: #selector(YourViewController.buttonAction(_:)),
             forControlEvents: .TouchUpInside)


func buttonAction(sender: UIButton!) {
    let selectedButton = sender as! UIButton
    print(selectedButton.tag) // here stands the correct button which is pressed
}

You could also create an Array containing all Buttons, for example:

let myButtons = [UIButton]()
let button1 = UIButton()...
button1.tag = 0
myButtons.add(button1)

And now change it like this way:

myButtons[0].setImage(.....)

Where 0 is your first button (so with tag 0) // you should set your tags in the same order in which you append it to your myButtons Array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM