6

I'm trying to add views(or buttons) to UIStackView dynamically.

At first, the UIStackView has no arranged views (vertically), and after getting from some http response, several views(buttons) are added to UIStackView. UIStackView is also autolayout to hold a specific area. I've tried to find dynamic adding example, but failed.

Anyone can show me the examples of adding view onto UIStackView dynamically?

Dilip Tiwari
  • 1,441
  • 18
  • 31
GT Kim
  • 329
  • 1
  • 4
  • 16

3 Answers3

8

It may help you. Please follow this points:

  • Add UIScrollView to your UIViewController in storyboard or XIB.
  • Initiate an NSMutableArray name it arrViews gets server response and adds view in the array.
  • Initialise UIStackViewpass arrView array in the init method.
  • After that UIStackView will be added subview of UIScrollView.
  • Add constraint programmatically to UIStackView. That's it.

    if let response = self.serverResponse {
        if let body = response.responseBody {
    
            if let view = body.views {
                arrViews =  createSubViews(view)
            }
    
        }
    }
    
    let stackView = UIStackView(arrangedSubviews: arrViews)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.axis = .vertical
    stackView.spacing = 16
    stackView.distribution = .fill
    self.scrollView.addSubview(stackView)
    
    //constraints
    
    let leading = NSLayoutConstraint(item: stackView, attribute: .leading, relatedBy: .equal, toItem: self.scrollView, attribute: .leading, multiplier: 1.0, constant: 0)
    self.scrollView.addConstraint(leading)
    let trailing = NSLayoutConstraint(item: stackView, attribute: .trailing, relatedBy: .equal, toItem: self.scrollView, attribute: .trailing, multiplier: 1.0, constant: 0)
    self.scrollView.addConstraint(trailing)
    let top = NSLayoutConstraint(item: stackView, attribute: .top, relatedBy: .equal, toItem: self.scrollView, attribute: .top, multiplier: 1.0, constant: 0)
    self.scrollView.addConstraint(top)
    
    let bottom = NSLayoutConstraint(item: stackView, attribute: .bottom, relatedBy: .equal, toItem: self.scrollView, attribute: .bottom, multiplier: 1.0, constant: 0)
    self.scrollView.addConstraint(bottom)
    
    let equalWidth = NSLayoutConstraint(item: stackView, attribute: .width, relatedBy: .equal, toItem: self.scrollView, attribute: .width, multiplier: 1.0, constant: 0)
    
    self.scrollView.addConstraint(equalWidth)
    
    
    leading.isActive = true
    trailing.isActive = true
    top.isActive = true
    bottom.isActive = true
    equalWidth.isActive = true
    

Hope it will help you. Happy coding :)

iamVishal16
  • 1,780
  • 18
  • 40
5

I use this code in one of my projects:

    let baseFrame = CGRect(origin: .zero, size: CGSize(width: requiredWidth, height: partitionHeight))
    for instrument in instruments {
        let partitionView = PartitionOnDemand(instrument: instrument, mode: playbackMode, frame: baseFrame, referenceView: partitionsAnimator)
        partitionsStackView.addArrangedSubview(partitionView)
        let tab = InstrumentInfoTabContainer.instantiate(with: instrument) {
            self.focus(on: instrument)
        }
        tabsStackView.addArrangedSubview(tab)
    }
halfer
  • 19,824
  • 17
  • 99
  • 186
ekscrypto
  • 3,718
  • 1
  • 24
  • 38
-1

While trying with answers, I happend to find how to work it.

class ViewController: UIViewController {

@IBOutlet weak var stack: UIStackView!
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
@IBAction func onBtn_Create(_ sender: Any) {
    createButton("new button ...")
}
@IBAction func onBtn_Delete(_ sender: Any) {
    if let v = stack.arrangedSubviews.last {
        stack.removeArrangedSubview(v)
        v.removeFromSuperview()
    }

}


func createButton(_ title: String) {
    let button = UIButton()
    button.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
    button.backgroundColor = UIColor.blue
    button.setTitle(title, for: .normal)
    button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)

    stack.addArrangedSubview(button)
}


@objc func buttonAction(sender: UIButton!) {
    print("Button tapped")
}

}

And, I anchored to UIStackView, Trailing=0, Leading=0, Top=0, Bottom=8 to TextView.Top

The subviews inside it are intact without any constraints.

Thank you.enter image description here

GT Kim
  • 329
  • 1
  • 4
  • 16