#ios #swift #uistackview
Вопрос:
Я пытаюсь отобразить динамически изменяемый размер UITextView
внутри представления стека, но текстовое представление не подстраивается под размер содержимого.
Сначала у меня есть упорядоченное подвидо:
class InfoView: UIView {
private var title: String!
private var detail: String!
private var titleLabel: UILabel!
private var detailTextView: UITextView!
init(infoModel: InfoModel) {
self.title = infoModel.title
self.detail = infoModel.detail
super.init(frame: .zero)
configure()
setConstraint()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configure() {
titleLabel = UILabel()
titleLabel.text = title
titleLabel.font = .rounded(ofSize: titleLabel.font.pointSize, weight: .bold)
titleLabel.textColor = .lightGray
titleLabel.sizeToFit()
titleLabel.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(titleLabel)
detailTextView = UITextView()
detailTextView.sizeToFit()
detailTextView.text = detail
detailTextView.font = UIFont.systemFont(ofSize: 19)
detailTextView.isEditable = false
detailTextView.textColor = .lightGray
detailTextView.isUserInteractionEnabled = false
detailTextView.isScrollEnabled = false
detailTextView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(detailTextView)
}
private func setConstraint() {
NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: self.topAnchor),
titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5),
titleLabel.heightAnchor.constraint(equalToConstant: 40),
detailTextView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor),
detailTextView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
detailTextView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
detailTextView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
}
}
Затем я реализую представление стека в контроллере представления:
class MyViewController: UIViewController {
var infoModelArr: [InfoModel]!
var stackView: UIStackView!
var scrollView: UIScrollView!
init(infoModelArr: [InfoModel]) {
self.infoModelArr = infoModelArr
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
var infoViewArr = [InfoView]()
for infoModel in infoModelArr {
let infoView = InfoView(infoModel: infoModel)
infoViewArr.append(infoView)
}
stackView = UIStackView(arrangedSubviews: infoViewArr)
stackView.axis = .vertical
stackView.spacing = 10
stackView.distribution = .fillProportionally
stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
stackView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.contentSize = stackView.bounds.size
}
}
Наконец, я вызываю контроллер представления следующим образом:
let myVC = MyViewController(infoModelArr: [InfoModel(title: "title", detail: "detail"), InfoModel(title: "title", detail: "detail")])
self.present(myVC, animated: true, completion: nil)
Примечательно, что если бы я создал экземпляр представления стека с одним упорядоченным подвидом, высота представления стека, по-видимому, динамически корректируется, но как только вводятся 2 или более подвидов, высота не отражает содержимое.
Когда я попытался установить внутренний размер InfoView
,
override func layoutSubviews() {
super.layoutSubviews()
height = titleLabel.bounds.height detailTextView.bounds.height
}
var height: CGFloat! = 200 {
didSet {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
let originalSize = super.intrinsicContentSize
return CGSize(width: originalSize.width, height: height)
}
detailTextView.bounds.height
возвращает 0.
Комментарии:
1. Вы пытаетесь изобрести
UITableView
что-то новое ? Похоже, вы используетеUIScrollView
его неправильно (вы даже не инициализировали его?).fillProportionally
здесь тоже не кажется уместным. Должны же быть какие-то ограничения, верно? Вы должны включить конфликтующие ограничения в свой вопрос. Я думаюfill
, что это более уместно, но почему вы вообще не используете aUITableView
?2. @Sweeper упс отсутствие
UIScrollView
было ошибкой с моей стороны в копировании вопроса.fill
похоже, это делает свое дело, поэтому, если вы хотите опубликовать ответ, я отмечу его. Я используюUIStackView
, потому что я буду использовать только 1-3 элемента, но я определенно буду учитывать этот вариант.
Ответ №1:
На fillProportionally
распределение пытается шкалы высот организованы подпанелей по их подлинным содержанием размер, как часть стека вид на высоте. например, если стек вид имеет высоту 120, а также организовать рабочую панель также имеет внутреннюю высоту 10, и устраивается панель Б имеет внутреннюю высоту 20, а затем A и B будет иметь высоту в 40 и 80 соответственно в стеке вид.
Ваш вид стека не имеет определенной высоты, поэтому fillProportionally
здесь нет особого смысла.
Вместо этого распределение fill
должно выполнять эту работу:
stackView.distribution = .fill
(в качестве эксперимента вы можете попробовать добавить ограничение по высоте в представление стека, и вы увидите, как fillProportionally
это работает)