what is wrong with my StackView? This is the code:
class PushUpViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setUpStackView()
}
func setUpStackView() {
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .fillProportionally
stackView.spacing = 50
view.addSubview(stackView)
// SetUp StackView Constraints:
stackView.pin(to: view)
stackView.setCustomSpacing(50, after: PushUpButton)
stackView.setCustomSpacing(100, after: TimeLabel)
// Set Elements to StackView:
stackView.addArrangedSubview(TimeLabel)
stackView.addArrangedSubview(PushUpButton)
stackView.addArrangedSubview(secondStackView)
// SetUp PushUpButton:
PushUpButton.backgroundColor = .white
PushUpButton.setTitle("\(count)", for: .normal)
PushUpButton.setTitleColor(.systemGray, for: .normal)
PushUpButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 70)
PushUpButton.translatesAutoresizingMaskIntoConstraints = false
PushUpButton.heightAnchor.constraint(equalToConstant: 300).isActive = true
PushUpButton.widthAnchor.constraint(equalToConstant: 150).isActive = true
// SetUp TimeLabel
TimeLabel.textAlignment = .center
TimeLabel.text = "\(counter)"
TimeLabel.textColor = .black
TimeLabel.font = .boldSystemFont(ofSize: 30)
self.view.addSubview(TimeLabel)
TimeLabel.translatesAutoresizingMaskIntoConstraints = false
TimeLabel.widthAnchor.constraint(equalToConstant: 300).isActive = true
TimeLabel.heightAnchor.constraint(equalToConstant: 200).isActive = true
// SetUp SecondStackView
secondStackView.translatesAutoresizingMaskIntoConstraints = false
secondStackView.axis = .horizontal
secondStackView.alignment = .center
secondStackView.distribution = .fillEqually
secondStackView.spacing = 20
// SetUp SecondStackView Constrains
secondStackView.heightAnchor.constraint(equalToConstant: 50).isActive = true
secondStackView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -15).isActive = true
// Set Elements:
secondStackView.addArrangedSubview(breakButton)
secondStackView.addArrangedSubview(stopbutton)
//SetUp BreakButton
breakButton.backgroundColor = .lightGray
breakButton.setTitle("Break", for: .normal)
breakButton.setTitle("Start", for: .selected)
breakButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
breakButton.setTitleColor(.white, for: .normal)
breakButton.layer.cornerRadius = 12
breakButton.layer.borderWidth = 1
breakButton.layer.borderColor = UIColor.white.cgColor
// breakButton.addTarget(self, action: #selector(BreakButtonTapped), for: .touchUpInside)
breakButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
breakButton.widthAnchor.constraint(equalToConstant: 150),
breakButton.heightAnchor.constraint(equalToConstant: 50)
])
// SetUp StopButton:
stopbutton.backgroundColor = .systemRed
stopbutton.setTitle("Stop", for: .normal)
stopbutton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
stopbutton.setTitleColor(.white, for: .normal)
stopbutton.layer.cornerRadius = 12
stopbutton.layer.borderWidth = 1
stopbutton.layer.borderColor = UIColor.white.cgColor
// stopbutton.addTarget(self, action: #selector(stopButtonTapped), for: .touchUpInside)
stopbutton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stopbutton.widthAnchor.constraint(equalToConstant: 150),
stopbutton.heightAnchor.constraint(equalToConstant: 50)
])
}
}
But it should looks like this:
This is what comes in the console when I am on the StackView VC:
I have no idea what this means or what I should do to solve this problem
I do not understand StackViews... I watched a lot of yt tutorials but they are all the same and did't help me. My biggest problem is the distribution of the StackView: I don't know where the difference is
First tip: forget using .fillProportionally
with stack views. It is almost never used ... and when it is used, it's used for very specific reasons.
Second tip: during development, give your UI elements contrasting background colors to make it easy to see the frames at run-time.
Third tip: Use leadingLowerCase
for variable and function names... Use LeadingUpperCase
for class names.
Fourth tip: group similar code together - such as setting view properties, setting constraints, etc - and include logical comments to make it easier to follow what your code is doing.
Take a look at this:
class PushUpViewController: UIViewController {
let stackView = UIStackView()
let secondStackView = UIStackView()
let pushUpButton = UIButton()
let breakButton = UIButton()
let stopbutton = UIButton()
let timeLabel = UILabel()
var count: Int = 0
var counter: Float = 0.0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setUpStackView()
}
func setUpStackView() {
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .fill
stackView.distribution = .fill
// SetUp timeLabel
timeLabel.textAlignment = .center
timeLabel.text = "\(counter)"
timeLabel.textColor = .black
timeLabel.font = .boldSystemFont(ofSize: 30)
// SetUp pushUpButton:
pushUpButton.backgroundColor = .white
pushUpButton.setTitle("\(count)", for: .normal)
pushUpButton.setTitleColor(.systemGray, for: .normal)
pushUpButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 70)
// SetUp secondStackView
secondStackView.axis = .horizontal
secondStackView.alignment = .fill
secondStackView.distribution = .fillEqually
secondStackView.spacing = 20
//SetUp breakButton
breakButton.backgroundColor = .lightGray
breakButton.setTitle("Break", for: .normal)
breakButton.setTitle("Start", for: .selected)
breakButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
breakButton.setTitleColor(.white, for: .normal)
breakButton.layer.cornerRadius = 12
breakButton.layer.borderWidth = 1
breakButton.layer.borderColor = UIColor.white.cgColor
// SetUp stopButton:
stopbutton.backgroundColor = .systemRed
stopbutton.setTitle("Stop", for: .normal)
stopbutton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
stopbutton.setTitleColor(.white, for: .normal)
stopbutton.layer.cornerRadius = 12
stopbutton.layer.borderWidth = 1
stopbutton.layer.borderColor = UIColor.white.cgColor
// add buttons to horizontal second stack view
secondStackView.addArrangedSubview(breakButton)
secondStackView.addArrangedSubview(stopbutton)
// if we want the center PushUpButton to be 300 x 150
// and centered vertically
// we need to embed it in a clear view
let holderView = UIView()
// add PushUpButton to holderView
holderView.addSubview(pushUpButton)
// views added as arrangedSubviews of a stack view automatically get
// .translatesAutoresizingMaskIntoConstraints = false
// but, because we're adding the PushUpButton as a subview
// of holderView, we need to set it here
pushUpButton.translatesAutoresizingMaskIntoConstraints = false
// add views to stack view
stackView.addArrangedSubview(timeLabel)
stackView.addArrangedSubview(holderView)
stackView.addArrangedSubview(secondStackView)
// add stackView to view
view.addSubview(stackView)
// SetUp StackView Constraints:
//stackView.pin(to: view)
// respect safe-area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain stackview to full view (safe-area)
// to bottom with Zero extra space
stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
// to top with 20-pts "padding"
stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
// and 8-pts "padding" on each side
stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
// pushUpButton should be 300x150
pushUpButton.widthAnchor.constraint(equalToConstant: 300.0),
pushUpButton.heightAnchor.constraint(equalToConstant: 150.0),
// pushUpButton should be centered in holderView
pushUpButton.centerXAnchor.constraint(equalTo: holderView.centerXAnchor),
pushUpButton.centerYAnchor.constraint(equalTo: holderView.centerYAnchor),
// bottom buttons should have Height: 50
secondStackView.heightAnchor.constraint(equalToConstant: 50.0),
])
// break and stop button actions
//breakButton.addTarget(self, action: #selector(BreakButtonTapped), for: .touchUpInside)
//stopbutton.addTarget(self, action: #selector(stopButtonTapped), for: .touchUpInside)
// during development, so we can see the layout easily
//holderView.backgroundColor = .yellow
//PushUpButton.backgroundColor = .green
//TimeLabel.backgroundColor = .cyan
}
}
Result on iPhone 11:
on iPhone 8:
and with background colors to help during development:
Additional Tip:
When learning auto layout (particularly stack views), work on your layout in Storyboard / Interface Builder. You can immediately see how it looks and what happens when changing values / properties. You can also change the View as: to immediately see how it looks on different devices / screen sizes. If you want to keep everything in code, once you have your layout looking the way you want, then replicate those constraints and settings in code.