Autolayout: NSStackView не изменяет размер родительского представления при динамическом изменении высоты

Аналогичный вопрос: Как изменить размер родительского представления в зависимости от размера вложенных представлений, созданных с помощью Autolayout

У меня есть NSStackView, который загружает DisclosureViewControllers (подклассы NSViewController), как в примере Apple InfoBarStackView.

Пример InfoBarStackView от Apple

Они могут расширять и убирать виды произвольной высоты. Я хотел бы, чтобы родительский вид, содержащий NSStackView, изменил свою высоту в соответствии с содержимым NSStackView. В примере с Apple это работает.

Однако, к сожалению, Apple изменяет размер NSWindow, и я использую CCNStatusItem (CCNStatusItem Github), представление который прикреплен к элементу состояния в строке меню Apple. Размер этого окна изменяется до содержимого NSStackView при загрузке, но не изменяется при изменении содержимого.

Окно CCNStatusItem после загрузки представления

Когда я расширяю раздел, содержимое выходит за пределы и обрезается по нижнему краю представления.

Окно CCNStatusItem с расширенным DisclosureViewController

Я прошел через все ограничения и попытался воспроизвести его в точности, но не смог заставить его работать. В примере Apple все добавляют программно, а я добавил NSStackView в Interface Builder.

Вот ограничения NSStackView:  введите описание изображения здесь

Мой вопрос: какие ограничения у меня есть в Interface Builder (с какими приоритетами), чтобы размер родительского представления (окна) динамически изменялся в зависимости от содержимого представления стека? Должен ли я вызывать какой-то метод представления, чтобы оно работало?

Пожалуйста, дайте мне знать, если я пропустил некоторую необходимую информацию.

ОБНОВЛЕНИЕ

Принятый ответ был правильным способом сделать это. Вот результат. Мою разветвленную версию CCNStatusItem можно найти по адресу https://github.com/julianvogels/CCNStatusItem.git

Теперь слайд работает!


person Julian Vogels    schedule 27.08.2015    source источник


Ответы (2)


Проблема в том, что CCNStatusItem не поддерживает автоматическую компоновку. Он устанавливает представление содержимого своего окна как экземпляр одного из собственных классов представления (CCNStatusItemWindowBackgroundView). Ваше представление является частью этого представления.

Когда он создает и добавляет свое представление, он не выключает translatesAutoresizingMaskIntoConstraints и не использует ограничения для его расположения относительно своего супервизора. Это в основном означает, что его нельзя принудительно установить на другой размер из-за ограничений.

Точно так же, когда он добавляет ваше представление к фоновому представлению, он не выключает translatesAutoresizingMaskIntoConstraints на вашем представлении и не устанавливает ограничений, чтобы связать ваше представление с фоновым представлением.

Поскольку у вас есть исходный код, вы можете внести эти изменения.

person Ken Thomases    schedule 07.09.2015
comment
Я форкнул репозиторий CCNStatusItem и внес следующие изменения: 1. Добавил translatesAutoresizingMaskIntoConstraints в userConentView в CCNStatusItemWindow.m. 2. Прикрепил userContentView к краям с ограничениями в коде Теперь отлично работает! Единственный облом - теперь содержимое окна смещено вверх, но это, наверное, другая проблема. - person Julian Vogels; 08.09.2015
comment
Смещение к верхней части супервизора было постоянным, поэтому я мог просто продолжить и отрегулировать перья в IB. Проблема решена, теперь все в порядке. - person Julian Vogels; 08.09.2015

При использовании ограничений автоматической компоновки вам не нужно вызывать метод представления, чтобы вызвать этот эффект, просто убедитесь, что:

  • у представлений внутри представления стека есть ограничения, которые заставят их расти
  • контейнер имеет ограничения для представления стека, которые указывают, что контейнер должен расти вместе с представлением стека
  • у контейнера нет ограничений, которые мешали бы ему расти

Скриншоты вроде бы говорят, что это не первый - просмотры растут как положено. Так что это могло быть либо второе, либо третье. Скриншот из построителя интерфейса, кажется, показывает, что нижнее ограничение StackView ‹> Контейнер является необязательным (оно выделено пунктиром). В зависимости от того, каков на самом деле приоритет, это может быть вашей проблемой. Исходя из описанного вами дизайна, не должно быть причин, по которым это ограничение не является обязательным.

person Taylor    schedule 07.09.2015
comment
Вы правы, пунктирное ограничение имеет низкий приоритет (750). Я играл с этим, но с любым приоритетом он не сдвинулся с места. В общем, то, что вы описали, было бы правильным, но в моем случае это не сработало. Ответ @Ken Thomases, кажется, раскрывает суть проблемы. - person Julian Vogels; 08.09.2015
comment
Ах, рад, что вы нашли первопричину. Это попадет в третий случай (контейнер имеет ограничения маски автоматического изменения размера, которые не позволяют ему расти) - person Taylor; 08.09.2015