Atif Shabeer
Atif Shabeer

Reputation: 167

Dynamically add buttons in swift

I am writing an iOS app. Server gives me buttons array to draw on view. So, the number of buttons can vary according to server response, example:

let buttonArray=["Button 1","Button 2","Button 3"]
or
let buttonArray=["Button 1","Button 2","Button 3"," Button 4", "Button 5"]

I have to stack these buttons vertically. I created a stackview, add constraints to it, and then add buttons to this stackview as arrangedsubviews. Buttons should have gap of 5 points between them:

Using stackview:

func addButtonsUsingStackView()
    {
        //create stackview:
        let stackView=UIStackView()
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        stackView.alignment = .fill
        stackView.spacing = 5
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)

        //stackview constraints:
        let viewsDictionary = ["stackView":stackView]
        let stackView_H = NSLayoutConstraint.constraints(
            withVisualFormat: "H:|-20-[stackView]-20-|",
            options: NSLayoutFormatOptions(rawValue: 0),
            metrics: nil,
            views: viewsDictionary)
        let stackView_V = NSLayoutConstraint.constraints(
            withVisualFormat: "V:|-30-[stackView]-30-|",
            options: NSLayoutFormatOptions(rawValue:0),
            metrics: nil,
            views: viewsDictionary)
        view.addConstraints(stackView_H)
        view.addConstraints(stackView_V)

        //adding buttons to stackview:

        //let buttonArray=["Button 1","Button 2","Button 3"]
        let buttonArray=["Button 1","Button 2","Button 3"," Button 4"]

        for buttonName in buttonArray{

            let button=UIButton()
            button.setTitle(buttonName, for: .normal)
            button.setTitleColor(UIColor.white, for: .normal)
            button.backgroundColor=UIColor.blue
            button.translatesAutoresizingMaskIntoConstraints=false

            stackView.addArrangedSubview(button)

        }

    }

Without stackview:

var buttonArray=["Button 1","Button 2","Button 3"," Button 4"," Button 5"," Button 6"," Button 7"]

    func addButtonsLoop()
    {

        for _view in view.subviews{
            _view.removeFromSuperview()
        }

        var i=0
        var buttonY = 20
        let buttonGap=5

        for btn in buttonArray {

            let buttonHeight=Int(Int(view.frame.height) - 40 - (buttonArray.count * buttonGap))/buttonArray.count
            print(buttonHeight)
            let buttonWidth=Int(view.frame.width - 40)

            let button = UIButton()
            button.backgroundColor = UIColor.orange
            button.setTitle(btn, for: .normal)
            button.titleLabel?.textColor = UIColor.white
            button.frame = CGRect(x: 20, y: buttonY, width:buttonWidth , height:buttonHeight)
            button.contentMode = UIViewContentMode.scaleToFill
            buttonY += buttonHeight + buttonGap
            button.tag = i
            button.addTarget(self, action: #selector(self.buttonTapped(_:)), for: UIControlEvents.touchUpInside)
            view.addSubview(button)

            i+=1

        }
    }

    func buttonTapped( _ button : UIButton)
    {
        buttonArray.remove(at: button.tag)
        addButtonsLoop()
    }

My question is that instead of above code, how to apply NSLayoutConstraints or LayoutAnchors to solve this?

Upvotes: 1

Views: 9000

Answers (3)

Maxim Rysevets
Maxim Rysevets

Reputation: 155

Use NSButton when AppKit, or UIButton when UIKit:

override func viewDidLoad() {
    super.viewDidLoad()
    let button = NSButton()
    button.title = "My Button"
    self.view.addSubview(button)
    button.frame = CGRect(x: 0, y: 0, width: 100, height: 30)
}

Upvotes: -1

Nishant Bhindi
Nishant Bhindi

Reputation: 2252

you can use scroll view to add buttons.

var btnY = 5
let btnHeight = 40
func addButtonsUsingStackView()
        {
    for view in self.view.subviews{
                view.removeFromSuperview()
            }

            for i in 0..< buttonArray.count {

                let btnFloor = UIButton()
                btnFloor.backgroundColor = Orange       
                btnFloor.titleLabel?.textColor = UIColor.white
                btnFloor.frame = CGRect(x: 10, y: btnY, width: Int(scrView.frame.width - 20), height: btnHeight)
                btnFloor.contentMode = UIViewContentMode.scaleToFill
                btnY += btnHeight + 5
                btnFloor.tag = buttonArray.index(of: i)
                btnFloor.addTarget(self, action: #selector(self.btnTappedFloor(_:)), for: UIControlEvents.touchUpInside)
                self.view.addSubview(btnFloor)
            }
            return cell
        }

 func btnTappedFloor( _ button : UIButton)
 {
      buttonArray.remove(at: button.tag)
      addButtonsUsingStackView()
}

Upvotes: 1

Aravind A R
Aravind A R

Reputation: 2714

Instead of stack view you can use a tableview with the tableview cell containing a button and the number of rows can be the buttonarray count. In cellForRowAtIndexPath delegate method set the button title from button array.

Upvotes: 1

Related Questions