Search code examples
iosswiftnslayoutconstraint

Creating UIStackView programmatically - not displaying


I am trying to create a stackview programmatically but the view does not appear to present it self in a viewcontroller.

My code is below and the resultant screenshot of what I am getting. How do I get the stackview to start from the bottom of the navigationbar?

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    createDropDownMenu()
}

private func createDropDownMenu(){

    let editButton = UIButton()
    editButton.titleLabel?.text = "Edit"
    editButton.backgroundColor = UIColor.appBlue.withAlphaComponent(0.5)

    let createFolderButton = UIButton()
    createFolderButton.titleLabel?.text = "Create Folder"
    createFolderButton.backgroundColor = UIColor.appBlue.withAlphaComponent(0.5)

    let SignOutButton = UIButton()
    SignOutButton.titleLabel?.text = "Sign Out"
    SignOutButton.backgroundColor = UIColor.appBlue.withAlphaComponent(0.5)

    // StackView
    let stackView = UIStackView()
    stackView.axis = .vertical
    stackView.distribution = .equalSpacing
    stackView.alignment = .center
    stackView.spacing = 20

    stackView.addArrangedSubview(createFolderButton)
    stackView.addArrangedSubview(editButton)
    stackView.addArrangedSubview(SignOutButton)

    editButton.translatesAutoresizingMaskIntoConstraints = false
    editButton.heightAnchor.constraint(equalToConstant: 70).isActive = true
    editButton.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true

    createFolderButton.translatesAutoresizingMaskIntoConstraints = false
    createFolderButton.heightAnchor.constraint(equalToConstant: 70).isActive = true
    createFolderButton.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true

    SignOutButton.translatesAutoresizingMaskIntoConstraints = false
    SignOutButton.heightAnchor.constraint(equalToConstant: 70).isActive = true
    SignOutButton.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true

    view.addSubview(stackView)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    stackView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    stackView.heightAnchor.constraint(equalToConstant: 400).isActive = true
    stackView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true    
}
}

Screenshot:

enter image description here


Solution

  • You need an x constraint as you set centerY , top , width and height auto-layout won't know where in terms of x space to place the stackview , so replace

    stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    

    with

    stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    

    and that if you don't need it centered vertically as also it's not logical to set a top constraint and centerY at the same time plus you give each button a height constraint and set them inside a stack with predefined height with no proper distribution

    and remove

    stackView.heightAnchor.constraint(equalToConstant: 400).isActive = true
    

    Then replace

    stackView.distribution = .equalSpacing
    

    with

    stackView.distribution = .fill
    

    If you need it centered vertically and horizontally , then do

    NSLayoutConstraint.activate([ 
      stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
      stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor), 
      stackView.widthAnchor.constraint(equalTo: view.widthAnchor)
    ])