Following along with Apple's guide here (I've done it programmatically instead), I've created 3 horizontal stack views nested inside a vertical stack view. To make the text fields align, they're each in a horizontal stack view as well.
Is there a way to scoot over the text field stack views so that I can see the 3-character placeholder text? I've tried .fill
, .fillProportionally
, and the others as well, but the horizontal stack views end up 50/50 with the labels
I'm new to autolayout, so I'm building this as a learning exercise. There has to be a better way to do this, right?
Something like this (1/4-1/3 space for labels and 2/3-3/4 for text fields).
import UIKit
class RunningPaceCalculatorViewController: UIViewController {
private lazy var timeDistancePaceStackView: UIStackView = {
let timeStackView = UIStackView.textFieldsStackView("Time")
let distanceStackView = UIStackView.distanceStackView()
let paceStackView = UIStackView.textFieldsStackView("Pace")
return UIStackView.customStackView(.vertical, backgroundColor: .systemTeal, subviews: [timeStackView, distanceStackView, paceStackView])
}()
private lazy var buttonStackView: UIStackView = {
return UIStackView.buttonStackView()
}()
private lazy var constainerStackView: UIStackView = {
return UIStackView.customStackView(.vertical, backgroundColor: .gray, subviews: [timeDistancePaceStackView, buttonStackView])
}()
override func viewDidLoad() {
setUpView()
}
func setUpView() {
view.backgroundColor = .orange
view.addSubview(constainerStackView)
NSLayoutConstraint.activate([
constainerStackView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.55),
constainerStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
constainerStackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
constainerStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
constainerStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10)
])
}
}
private extension UITextField {
static func customTextField(_ placeholder: String) -> UITextField {
let textField = UITextField()
textField.placeholder = placeholder
textField.backgroundColor = .white
return textField
}
}
private extension UIStackView {
static func customStackView(_ orientation: NSLayoutConstraint.Axis, distribution: UIStackView.Distribution = UIStackView.Distribution.fill, backgroundColor: UIColor, subviews: [UIView]) -> UIStackView {
let stackView = UIStackView(arrangedSubviews: subviews)
stackView.axis = orientation
stackView.distribution = .fillEqually
stackView.backgroundColor = backgroundColor
stackView.spacing = 5.0
stackView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 2, leading: 2, bottom: 2, trailing: 2)
stackView.isLayoutMarginsRelativeArrangement = true
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}
static func textFieldsStackView(_ title: String) -> UIStackView {
let COLON = ":"
let label = UILabel.customLabel(title)
label.setContentHuggingPriority(.defaultHigh + 1, for: .horizontal)
label.setContentHuggingPriority(.defaultHigh + 1, for: .vertical)
let paceTextField1 = UITextField.customTextField("Hrs")
let colonLabel1 = UILabel.customLabel(COLON)
let paceTextField2 = UITextField.customTextField("Min")
let colonLabel2 = UILabel.customLabel(COLON)
let paceTextField3 = UITextField.customTextField("Sec")
let textFieldContainerStackView = UIStackView.customStackView(.horizontal, backgroundColor: .systemPink, subviews: [paceTextField1, colonLabel1, paceTextField2, colonLabel2, paceTextField3])
textFieldContainerStackView.setContentHuggingPriority(.defaultLow - 50, for: .horizontal)
textFieldContainerStackView.setContentCompressionResistancePriority(.defaultLow - 1, for: .horizontal)
return UIStackView.customStackView(.horizontal, distribution: .fill, backgroundColor: .systemBlue, subviews: [label, textFieldContainerStackView])
}
static func distanceStackView() -> UIStackView {
let DISTANCE = "Distance"
let label = UILabel.customLabel(DISTANCE)
let distanceTextField = UITextField.customTextField(DISTANCE)
return UIStackView.customStackView(.horizontal, distribution: .equalCentering, backgroundColor: .systemGray, subviews: [label, distanceTextField])
}
static func buttonStackView() -> UIStackView {
let calculateButton = UIButton.customButton("Calculate")
let resetButton = UIButton.customButton("Reset")
return UIStackView.customStackView(.horizontal, backgroundColor: .green, subviews: [calculateButton, resetButton])
}
}
private extension UIButton {
static func customButton(_ title: String) -> UIButton {
let button = UIButton()
button.setTitle(title, for: .normal)
return button
}
}
private extension UILabel {
static func customLabel(_ text: String) -> UILabel {
let timeLabel = UILabel()
timeLabel.text = text
return timeLabel
}
}