Существуют различные подходы к этой задаче. Вы можете найти это немного более гибким ...
Вместо вызова забавы c для вычисления явных значений, вы можете установить ограничения высоты упорядоченных подпредставлений в процентах от высоты стека. view.
Пара преимуществ:
- при изменении кадра стекового представления, возможно, при повороте устройства, нет необходимости что-либо пересчитывать
- Вы можете контролировать общее количество высота представления стека, ограничивая его (с помощью .heightAnchor или .bottomAnchor) или , устанавливая высоту одного из упорядоченных подпредставлений
- , если представление стека высота не постоянна, вы можете надежно установить ограничения в
viewDidLoad()
, не дожидаясь автоматического макета, чтобы определить высоту представления стека
Вот полный пример - он напечатает высоты из организованных Subviews для отладки консоли, как на viewDidAppear()
, так и на viewWillTransition(to size:...)
для подтверждения:
extension UIStackView {
func setHeightPercentageFill(values: [CGFloat]) {
guard values.count == arrangedSubviews.count else { return }
axis = .vertical
spacing = 0
distribution = .fill
for i in 0..<arrangedSubviews.count {
arrangedSubviews[i].heightAnchor.constraint(equalTo: heightAnchor, multiplier: values[i]).isActive = true
}
}
}
class StackPercentViewController: UIViewController {
let stack: UIStackView = {
let v = UIStackView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
let colors: [UIColor] = [.red, .green, .blue, .yellow]
colors.forEach {
let v = UIView()
v.backgroundColor = $0
stack.addArrangedSubview(v)
}
view.addSubview(stack)
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain stack view Top / Leading / Trailing at 40-pts
stack.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
stack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
stack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
])
// change "if true" to "if false" to test giving the stack view a height
if true {
// either give one arranged subview a height constraint
if let v = stack.arrangedSubviews.first {
v.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
}
} else {
// or, constrain the stack view's height (.heightAnchor or .bottomAnchor)
stack.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -40.0).isActive = true
//stack.heightAnchor.constraint(equalToConstant: 200.0).isActive = true
}
stack.setHeightPercentageFill(values: [0.20, 0.40, 0.30, 0.10])
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
checkHeights()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: nil, completion: {
_ in
self.checkHeights()
})
}
func checkHeights() {
// print heights of arrangedSubviews to debug console
stack.arrangedSubviews.forEach {
print($0.frame.size.height)
}
print() // blank line in console
}
}
Results ...
With first subview hei ght ограничено до 20:
![image](https://i.stack.imgur.com/e2WJX.png)
с стека высота ограничена до 200:
![image](https://i.stack.imgur.com/xhtlm.png)
с вид стека ограничено 40 пунктами со всех 4 сторон:
![image](https://i.stack.imgur.com/Sbudk.png)