I need trying to build a grid layout for my calculator buttons using UIStackView. I have created an array to generate the buttons accordingly.
I found this question, which really helped me but instead of repeating the button labels, I need to generate only one button per array item.
Here is a screenshot of the app at the moment: Wrong layout
And here is the desired layout: enter link description here
I have two questions:
1) How to make the grid elements with only unique array items instead of repeating the same item as button title per row?
2) How can I set the UILabel for the first button amountDisplayLabel to the button that is clicked (pressed)?
Here is the code I have been trying:
class StackViewGridController: UIViewController {
let numberLabel = UILabel()
let numberKeysArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", ""]
override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .white
    stackedGrid(rows: 4, columns: 1, rootView: view)
    print(numberLabel)
}
@objc func onButton(button: UIButton){
    let result = button.currentTitle ?? ""
    numberLabel.text = result
    print(result)
}
let amountDisplayLabel: UILabel = {
    let label = UILabel()
    label.backgroundColor = .green
    return label
}()
func stackedGrid(rows: Int, columns: Int, rootView: UIView){
    amountDisplayLabel.text = numberLabel.text
    // Init StackView
    let stackView = UIStackView()
    stackView.axis = .vertical
    stackView.alignment = .fill
    stackView.distribution = .fillEqually
    stackView.spacing = 5
    stackView.addArrangedSubview(amountDisplayLabel)
    for i in 1...numberKeysArray.count {
        let horizontalSv = UIStackView()
        horizontalSv.axis = .horizontal
        horizontalSv.alignment = .fill
        horizontalSv.distribution = .fillEqually
        horizontalSv.spacing = 5
        for _ in 1...columns {
            let button = UIButton()
            button.backgroundColor = .orange
            button.setTitle("\(i)", for: .normal)
            button.addTarget(self, action: #selector(onButton), for: .touchUpInside)
            horizontalSv.addArrangedSubview(button)
            amountDisplayLabel.text = button.currentTitle
        }
        stackView.addArrangedSubview(horizontalSv)
    }
    rootView.addSubview(stackView)
    fitParenLayout(stackView, parentView: rootView)
}
func fitParenLayout(_ child: UIView, parentView: UIView){
    amountDisplayLabel.bottomAnchor.constraint(equalTo: child.topAnchor)
    child.defineAnchors(top: parentView.safeTopAnchor, left: parentView.safeLeftAnchor, bottom: nil, right: parentView.safeRightAnchor, paddingTop: 10, paddingLeft: 10, paddingBottom: 10, paddingRight: 10)
}
}
Thanks,
here's your solution
import UIKit
class StackViewGridController: UIViewController {
    let numberKeysArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", "="]
    let mySpacing: CGFloat = 5.0
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        stackedGrid(rows: 4, columns: 3, rootView: view)
    }
    @objc func onButton(button: UIButton){
        amountDisplayLabel.text = button.currentTitle ?? ""
    }
    let amountDisplayLabel = UILabel()
    func stackedGrid(rows: Int, columns: Int, rootView: UIView){
        // Init StackView
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.alignment = .fill
        stackView.distribution = .fillEqually
        stackView.spacing = mySpacing
        amountDisplayLabel.backgroundColor = .green
        stackView.addArrangedSubview(amountDisplayLabel)
        for row in 0 ..< rows {
            let horizontalSv = UIStackView()
            horizontalSv.axis = .horizontal
            horizontalSv.alignment = .fill
            horizontalSv.distribution = .fillEqually
            horizontalSv.spacing = mySpacing
            for col in 0 ..< columns {
                let button = UIButton()
                button.backgroundColor = .orange
                button.layer.cornerRadius = 6
                button.setTitle("\(numberKeysArray[row*columns + col])", for: .normal)
                button.addTarget(self, action: #selector(onButton), for: .touchUpInside)
                horizontalSv.addArrangedSubview(button)
            }
            stackView.addArrangedSubview(horizontalSv)
        }
        rootView.addSubview(stackView)
        // add constraints
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.topAnchor.constraint(equalTo: rootView.topAnchor, constant: mySpacing).isActive = true
        stackView.leftAnchor.constraint(equalTo: rootView.leftAnchor, constant: mySpacing).isActive = true
        stackView.rightAnchor.constraint(equalTo: rootView.rightAnchor, constant: -mySpacing).isActive = true
        stackView.bottomAnchor.constraint(equalTo: rootView.bottomAnchor, constant: -mySpacing).isActive = true
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With