Определение размера контейнера с контроллером динамического размера внутри прокрутки
Я пытаюсь создать представление контейнера с контроллером с динамической высотой внутри UIScrollView и автоматически настроить его с помощью автоматического макета.
Раскадровка, иллюстрирующая настройку
View Controller A - это scrollview, в котором включен контейнерный вид, а также больше содержимого ниже.
View Controller B - контроллер представления, который я хочу иметь динамический размер, и для всего содержимого, которое будет отображаться на полной высоте в представлении View Controller A Scroll View.
У меня возникли проблемы с динамическим размером B, чтобы автоматически установить размер Container View в A. Однако, если я установил ограничение высоты на Контейнер в например, 250, это будет ожидаемый результат, если View Controller B также будет иметь 250 высот. Он также отлично работает на высоте 1000, насколько мне известно, все ограничения автоматической компоновки установлены правильно. К сожалению, поскольку высота должна быть динамической, я хотел бы избежать установки ограничения высоты на всех.
Я не уверен, есть ли какие-либо настройки для контроллера просмотра B, я могу установить для него автоматическое обновление его размера в зависимости от его содержимого или любые другие трюки, которые я пропустил. Любая помощь будет высоко оценена!
Есть ли какой-либо способ для размера Container View в в зависимости от того, насколько большой размер View Controller B не задает ограничение по высоте?
Ответы
Ответ 1
Да, есть. Мне удалось достичь такого поведения в одном из моих собственных проектов.
Все, что вам нужно сделать, это сообщить системе, что он не должен добавлять ограничения, которые имитируют фиксированный фрейм, установленный для вашего корневого представления в Interface Builder. Лучшее место для этого - в контроллере просмотра контейнера, когда срабатывает встроенный segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// You might want to check if this is your embed segue here
// in case there are other segues triggered from this view controller.
segue.destinationViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
}
Важно:
Вы должны убедиться, что представление, которое вы загружаете в контейнер, ограничено сверху вниз, и вам нужно установить приоритет одного из вертикальных ограничений на значение ниже 1000. (Хорошая практика всегда использовать нижнее ограничение для этого.) Это необходимо, потому что иначе Interface Builder будет жаловаться - с уважительной причиной:
Во время разработки ваш корневой вид имеет фиксированный размер (высота). Теперь, если все ваши подвидности имеют фиксированную высоту и связаны с фиксированными ограничениями, все из которых имеют одинаковый приоритет, невозможно выполнить все эти требования, если высота вашего фиксированного корневого представления по совпадению не совпадает с общей высотой ваших подзонов и вертикальными ограничениями. Если вы уменьшите приоритет одного из ограничений до 999, Interface Builder знает, какое ограничение прерывать. Однако во время выполнения - когда свойство translatesAutoresizingMaskIntoConstraints
установлено, как указано выше, больше нет фиксированного фрейма для вашего корневого представления, и вместо этого система будет использовать ограничение приоритета 999.
![Скриншот интерфейса Builder]()
Ответ 2
Из ответа @Mischa я смог сделать высоту динамика containerView в зависимости от его содержимого:
В viewController контейнераView пишите:
override func loadView() {
super.loadView()
view.translatesAutoresizingMaskIntoConstraints = false
}
И соблюдайте все вертикальные ограничения в IB. Для этого вам не нужно устанавливать view.translatesAutoresizingMaskIntoConstraints = false извне контроллера представления.
В моем случае я пытался изменить размер контейнера на tableView внутри viewController. Поскольку tableView имеет гибкую высоту в зависимости от своего супервизора (так что все ОК для IB), я выполнил вертикальные ограничения в коде, выполнив следующие действия:
@IBOutlet private var tableView: UITableView! {
didSet {
tableView.addConstraint(tableViewHeight)
}
}
private lazy var tableViewHeight: NSLayoutConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 0)
Затем обратите внимание на высоту contentSize таблицы и при необходимости скорректируйте константу ограничения tableViewHeight, когда это необходимо.
Ответ 3
Swift 4, Xcode 9
Только принятый ответ не разрешил проблему для меня.
Моя иерархия: ScrollView → Просмотр содержимого (UIView) → Просмотры | Просмотр контейнера | Другие виды.
Мне пришлось добавить следующие ограничения, чтобы динамически настроить как ScrollView, так и Container:
- ScrollView: верх, низ, ведущий, переход к надзору (безопасные зоны)
- Просмотр содержимого: верхняя, нижняя, ведущая, трейлинг, равная ширина для ScrollView, но также с равными высотами (ограничение с более низким приоритетом: 250).
- Просмотры: обычные ограничения автоматической компоновки.
- Просмотр контейнера: верхний, нижний к соседнему, ведущий и идущий в безопасную зону.
- Container View embedded VC: все ограничения связаны вертикально с нижним ограничением, установленным на более низкий приоритет, , но больше, чем просмотр содержимого равным по высоте! В этом случае, приоритет 500 сделал трюк.
- Установите
view.translatesAutoresizingMaskIntoConstraints = false
в prepareForSegue()
или в loadView()
, как указано в других ответах.
Теперь у меня есть динамически настраиваемый вид контейнера внутри прокрутки с автоматическим изменением размера.