Свойство .fillProportionally
UIStackView
(по моему опыту) является одним из самых неправильно понятых элементов автоматического макета.
Итак, я не совсем уверен, что это даст вам то, что Вы хотите, но попробуйте.
![enter image description here](https://i.stack.imgur.com/QJeJb.png)
Нажатие кнопки Text
изменит "описание" «текст и нажатие кнопки Height
изменит высоту представления« контейнер », так что вы можете увидеть, как он выглядит с различным количеством текста.
Кнопка Report
выведет итоговую высоту и пропорциональные rat ios просмотров.
Все через код - без @IBOutlet
или @IBAction
соединений - поэтому просто начните с нового контроллера представления и назначьте его пользовательский класс ProportionalStackViewController
:
class ProportionalHeightView: UIView {
let myNonScrollTextView: UITextView = {
let v = UITextView()
v.isScrollEnabled = false
v.setContentHuggingPriority(.required, for: .vertical)
return v
}()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
let padding: CGFloat = 0.0
addSubview(myNonScrollTextView)
myNonScrollTextView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
myNonScrollTextView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding),
myNonScrollTextView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding),
// if we want the text top-aligned
//myNonScrollTextView.topAnchor.constraint(equalTo: topAnchor),
// if we want the text vertically=sentered
myNonScrollTextView.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
override func layoutSubviews() {
super.layoutSubviews()
myNonScrollTextView.sizeToFit()
invalidateIntrinsicContentSize()
}
override var intrinsicContentSize: CGSize {
return myNonScrollTextView.bounds.size
}
}
class TitleView: ProportionalHeightView {
override func commonInit() {
super.commonInit()
myNonScrollTextView.font = UIFont.systemFont(ofSize: 22.0, weight: .bold)
myNonScrollTextView.backgroundColor = .cyan
backgroundColor = .blue
}
}
class DescView: ProportionalHeightView {
override func commonInit() {
super.commonInit()
myNonScrollTextView.font = UIFont.systemFont(ofSize: 17.0, weight: .regular)
myNonScrollTextView.backgroundColor = .yellow
backgroundColor = .orange
}
}
class ProportionalStackViewController: UIViewController {
var titleView: ProportionalHeightView = {
let v = ProportionalHeightView()
v.myNonScrollTextView.font = UIFont.systemFont(ofSize: 22.0, weight: .bold)
v.myNonScrollTextView.backgroundColor = .cyan
v.backgroundColor = .blue
return v
}()
var descView: ProportionalHeightView = {
let v = ProportionalHeightView()
v.myNonScrollTextView.font = UIFont.systemFont(ofSize: 16.0, weight: .regular)
v.myNonScrollTextView.backgroundColor = .yellow
v.backgroundColor = .orange
return v
}()
let containerView: UIView = {
let v = UIView()
v.backgroundColor = .white
return v
}()
let proportionalStackView: UIStackView = {
let v = UIStackView()
v.axis = .vertical
v.distribution = .fillProportionally
return v
}()
let changeTextButton: UIButton = {
let b = UIButton()
b.backgroundColor = .gray
b.setTitle("Text", for: .normal)
return b
}()
let changeHeightButton: UIButton = {
let b = UIButton()
b.backgroundColor = .gray
b.setTitle("Height", for: .normal)
return b
}()
let reportButton: UIButton = {
let b = UIButton()
b.backgroundColor = .gray
b.setTitle("Report", for: .normal)
return b
}()
let btnStack: UIStackView = {
let v = UIStackView()
v.distribution = .fillEqually
v.spacing = 20
return v
}()
var nLines = 0
var containerH = NSLayoutConstraint()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemTeal
btnStack.translatesAutoresizingMaskIntoConstraints = false
proportionalStackView.translatesAutoresizingMaskIntoConstraints = false
containerView.translatesAutoresizingMaskIntoConstraints = false
// add a horizontal stack view with buttons at the top
btnStack.addArrangedSubview(changeTextButton)
btnStack.addArrangedSubview(changeHeightButton)
btnStack.addArrangedSubview(reportButton)
view.addSubview(btnStack)
// set text for titleView
titleView.myNonScrollTextView.text = "Pleasanton Panthers"
descView.myNonScrollTextView.text = "A one stop destination for all the Panthers fans! Experience our new futuristic techology-enabled fan experience an much more!" // "Single line"
proportionalStackView.addArrangedSubview(titleView)
proportionalStackView.addArrangedSubview(descView)
containerView.addSubview(proportionalStackView)
view.addSubview(containerView)
// respect safe area
let g = view.safeAreaLayoutGuide
containerH = containerView.heightAnchor.constraint(equalToConstant: 240.0)
NSLayoutConstraint.activate([
// buttons stack 20-pts from top / leading / trailing
btnStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
btnStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
btnStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
// container view 20-pts from bottom of buttons, 20-pts from leading / trailing
containerView.topAnchor.constraint(equalTo: btnStack.bottomAnchor, constant: 20.0),
containerView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
containerView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
// container view height
containerH,
// constrain stack view 20-pts from top/bottom/leading/trailing to container
proportionalStackView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 20.0),
proportionalStackView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -20.0),
proportionalStackView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 20.0),
proportionalStackView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -20.0),
])
changeTextButton.addTarget(self, action: #selector(changeText), for: .touchUpInside)
changeHeightButton.addTarget(self, action: #selector(changeHeight), for: .touchUpInside)
reportButton.addTarget(self, action: #selector(report), for: .touchUpInside)
[titleView, titleView.myNonScrollTextView, descView, descView.myNonScrollTextView].forEach {
v in
// un-comment next line to clear background colors
//v.backgroundColor = .clear
}
}
@objc func report() -> Void {
let titleTextH = titleView.myNonScrollTextView.frame.size.height
let descTextH = descView.myNonScrollTextView.frame.size.height
let titleViewH = titleView.frame.size.height
let descViewH = descView.frame.size.height
let tRatio = titleTextH / descTextH
let vRatio = titleViewH / descViewH
print("text heights:\t", titleTextH, descTextH)
print("view heights:\t", titleViewH, descViewH)
print("Text view ratio: \(tRatio) view ratio: \(vRatio)")
}
@objc func changeHeight() -> Void {
if containerView.frame.origin.y + containerView.frame.size.height > view.frame.size.height - 20 {
containerH.constant = 220
}
containerH.constant += 20
}
@objc func changeText() -> Void {
nLines += 1
if nLines > 10 {
descView.myNonScrollTextView.text = "A one stop destination for all the Panthers fans! Experience our new futuristic techology-enabled fan experience an much more!" // "Single line"
nLines = 0
return
}
var s = ""
for i in 1..<nLines {
s += "Line \(i)\n"
}
s += "Line \(nLines)"
descView.myNonScrollTextView.text = s
}
}