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