Подтвердить что ты не робот

Определение размера контейнера с контроллером динамического размера внутри прокрутки

Я пытаюсь создать представление контейнера с контроллером с динамической высотой внутри 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 не задает ограничение по высоте?

4b9b3361

Ответ 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(), как указано в других ответах.

Теперь у меня есть динамически настраиваемый вид контейнера внутри прокрутки с автоматическим изменением размера.