#ios #swift #xcode #constraints
#iOS #swift #xcode #ограничения
Вопрос:
У меня есть представление view controller с 3 разделами столбцов (называемыми legs, aView
, bView
и cView
) по умолчанию. Пользователь может переключить его между 2 и 3 в меню настроек, которое модально отображается на том же экране.
Я пытаюсь добиться того, чтобы столбцы занимали одинаковое пространство на экране, поэтому, когда есть 3 столбца, каждый из них занимает примерно 1/3 ширины (игнорируя отступы), а когда их 2, каждый из них занимает примерно 1/2.
Мой текущий метод устанавливает некоторые ограничения, которые всегда активны, а затем для тех, которые меняются в зависимости от количества столбцов, используя if
инструкцию. Я пробовал некоторые варианты layoutIfNeeded()
, removeConstraints
и другие, но не совсем уверен, как их реализовать.
Для некоторых разъяснений по коду, xView
это представление столбца, которое содержит xTitle
и xTextView
. Также есть mainButton
над текстовыми представлениями и button1
под текстовыми представлениями. Все это существует внутри настройки contentView
и scrollView
.
let sidePadding: CGFloat = 15
func placeViews() { // run in viewWillAppear
let alwaysConstraints = [
aView.topAnchor.constraint(equalTo: mainButton.bottomAnchor, constant: 25),
aView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: sidePadding),
aView.rightAnchor.constraint(equalTo: bView.leftAnchor),
bView.topAnchor.constraint(equalTo: aView.topAnchor),
bView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
aTitle.topAnchor.constraint(equalTo: aView.topAnchor),
bTitle.topAnchor.constraint(equalTo: aTitle.topAnchor),
aTitle.centerXAnchor.constraint(equalTo: aView.centerXAnchor),
bTitle.centerXAnchor.constraint(equalTo: bView.centerXAnchor),
aTextView.topAnchor.constraint(equalTo: aTitle.bottomAnchor, constant: 25),
bTextView.topAnchor.constraint(equalTo: aTextView.topAnchor),
aTextView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
bTextView.bottomAnchor.constraint(equalTo: aTextView.bottomAnchor),
aTextView.centerXAnchor.constraint(equalTo: aView.centerXAnchor),
bTextView.centerXAnchor.constraint(equalTo: bView.centerXAnchor),
aTextView.widthAnchor.constraint(equalTo: aView.widthAnchor),
bTextView.widthAnchor.constraint(equalTo: bView.widthAnchor),
bView.widthAnchor.constraint(equalTo: aView.widthAnchor),
// Restrict buttons to leg views
button1.heightAnchor.constraint(equalToConstant: buttonHeight),
button1.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
button1.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
button1.topAnchor.constraint(equalTo: aView.bottomAnchor, constant: 40),
// Restrict button to bottom
button1.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20)
]
let twoLegConstraints = [
aView.widthAnchor.constraint(equalToConstant: (view.frame.width - (sidePadding * 2) / 2)),
bView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -sidePadding),
]
let threeLegConstraints = [
aView.widthAnchor.constraint(equalToConstant: (view.frame.width - (sidePadding * 2)) / 3),
bView.rightAnchor.constraint(equalTo: cView.leftAnchor),
cView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -sidePadding),
cView.topAnchor.constraint(equalTo: aView.topAnchor),
cView.bottomAnchor.constraint(equalTo: aView.bottomAnchor),
cTitle.topAnchor.constraint(equalTo: aTitle.topAnchor),
cTitle.centerXAnchor.constraint(equalTo: cView.centerXAnchor),
cTextView.topAnchor.constraint(equalTo: aTextView.topAnchor),
cTextView.bottomAnchor.constraint(equalTo: aTextView.bottomAnchor),
cTextView.centerXAnchor.constraint(equalTo: cView.centerXAnchor),
cTextView.widthAnchor.constraint(equalTo: cView.widthAnchor),
cView.widthAnchor.constraint(equalTo: aView.widthAnchor),
]
NSLayoutConstraint.activate(alwaysConstraints)
if legs == 2 {
cView.isHidden = true
NSLayoutConstraint.activate(twoLegConstraints)
} else if legs == 3 {
cView.isHidden = false
NSLayoutConstraint.activate(threeLegConstraints)
}
}
На данный момент экран по умолчанию начинается с 3, и он работает отлично (каждая ширина экрана ~ 1/3). Затем пользователь может переключить его на 2, и он снова работает идеально (каждая ширина экрана ~ 1/2). Затем, переключаясь обратно на 3, первые два вообще не меняются, а третий столбец появляется у правого края экрана.
Ответ №1:
Используйте представление стека с distribution = .fillEqually
. Он позаботится о макете и ограничениях автоматически, когда вы установите isHidden
свойство любого из ваших представлений.
Комментарии:
1. Тьфу, спасибо!! Это мое первое приложение, созданное полностью программно, так что это решение не бросилось мне в глаза. Я также узнал о необходимости использовать
addArrangedSubview
вместоaddSubview
для любых будущих читателей. Черт возьми, столько времени потрачено впустую. Спасибо!!2. Рад, что смог помочь!