Изменять размер супервизора после того, как subviews динамически меняются с помощью автозапуска

Я не могу любить бога, зависящего от этого изменения размера.

У меня есть UIView *superview с 4 UILabels. 2 - как заголовок для других.

Содержание во всех 4 динамически поступает из базы данных.

SizeToFit vs SizeThatFits:(CGSize) vs UIView systemLayoutSizeFittingSize:, передавая либо UILayoutFittingCompressedSize, либо UILayoutFittingExpandedSize.

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

где и как я могу использовать эти SizeToFit vs SizeThatFits:(CGSize) vs UIView systemLayoutSizeFittingSize:, передавая либо UILayoutFittingCompressedSize, либо UILayoutFittingExpandedSize. Я прочитал много советов здесь, в стеке, но ничего не получил.

Мне нужно пересчитать ограничения для супервизора где-то конкретным. Maby устанавливает высоту как "свойство @" в классе контроллера и удаляет и читает ее? Атм, я попытался все повсюду, а затем и некоторых. Тем не менее, я получаю конечный результат такого же размера, что и высота манекена, и текст, плавающий снаружи. Даже после установки clipToBound на subview.

Я царапаю свои волосы.. help

Ответ 1

Если вы используете автоматическую компоновку, вот что вам нужно сделать:

  • Убедитесь, что вы не добавляете ограничения фиксированной ширины и/или высоты в любое из ваших подзонов (в зависимости от того, какие размеры (размеры) вы хотите динамически изменять). Идея состоит в том, чтобы позволить внутреннему размеру содержимого каждого подсмотра определять высоту подсмотра. UILabel поставляется с 4 автоматическими неявными ограничениями, которые будут (с меньшим, чем Требуемый приоритет) попыткой сохранить рамку метки с точным размером, необходимым для размещения всего текста внутри.

  • Убедитесь, что края каждой метки жестко связаны (с обязательными ограничениями приоритета) к краям друг друга и их надписи. Вы хотите убедиться, что, если вы представляете один из ярлыков, растущих по размеру, это заставило бы другие ярлыки освободить место для него и, самое главное, заставить супервизор также расширяться.

  • Добавляйте ограничения для супервизора, чтобы установить его позицию, а не размер (по крайней мере, не для размеров (размеров), которые вы хотите, чтобы они динамически изменялись). Помните, что если вы правильно установили внутренние ограничения, размер будет определяться размерами всех подзонов, так как его ребра связаны с ними каким-то образом.

Что это. Вам не нужно вызывать sizeToFit или systemLayoutSizeFittingSize:, чтобы заставить это работать, просто загрузите свои представления и установите текст, и это должно быть оно. Механизм компоновки системы выполнит вычисления для решения ваших проблем. (Во всяком случае, вам может потребоваться вызвать setNeedsLayout в супервиде... но это не обязательно.)

Ответ 2

Использовать представления контейнера

В следующем примере у меня есть изображение 30x30, а UILabel меньше, чем содержащее представление с текстом-заполнителем. Мне нужно, чтобы содержащее представление было по крайней мере таким же большим, как изображение, но оно должно расти, чтобы содержать многострочный текст.

В визуальном формате внутренний контейнер выглядит следующим образом:

H:|-(15.0)-[image(30.0)]-(15.0)-[label]-(15.0)-|
V:|[image(30.0)]|
V:|[label(>=30.0)]|

Затем установите отображаемое представление в соответствие с высотой метки. Теперь содержащий вид будет показывать размер метки.

Как пояснил @smileyborg в своем ответе, жесткое подключение содержимого к супервизу, сообщает механизму компоновки, что простое представление контейнера должно заставить его расти.

Желтые прямоугольники выравнивания

Если вы хотите, чтобы желтые прямоугольники выравнивания добавляли -UIViewShowAlignmentRects YES в список схем параметров запуска.

UILabel that is multi-line

Ответ 3

Это стало значительно проще с представлением Stack Views в iOS 9. Используйте представление стека в вашем представлении, чтобы содержать весь ваш контент, который изменяет размер, а затем просто вызывайте

view.setNeedsUpdateConstraints()
view.updateConstraintsIfNeeded()
view.setNeedsLayout()
view.layoutIfNeeded()

после изменения содержимого. Затем вы можете получить свой новый размер, позвонив

view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

если вам когда-либо понадобится рассчитать точный размер, необходимый для просмотра.

Ответ 4

Это почти следует за ответом @smileyborg и поставляется с конкретным примером.

введите описание изображения здесь

Не будет описывать все ограничения, но те, которые связаны с вычислением высоты объектов пользовательского интерфейса.

  • [Ярлык] Ярлыки не должны иметь фиксированного ограничения height, в этом случае AutoLayout не будет изменять размер ярлыков, чтобы они соответствовали тексту, поэтому установка ограничений границ - это ключ. (зеленые стрелки)
  • [Subview] Шаги 1 и 3 очень просты в использовании, но этот шаг можно понять неправильно. Как и в случае с ярлыками, subviews не должен иметь набор ограничений height. Все подзадачи должны иметь набор ограничений top, игнорируя ограничение bottom, что может заставить вас думать, что это вызовет неудовлетворенное исключение ограничений во время выполнения, но это не произойдет, если вы установите ограничение bottom для последнего subview. Отсутствие этого приведет к размыванию макета. (красные стрелки)

  • [Superview] Установите все ограничения так, как вам нужно, но обратите большое внимание на height. Присвойте ему случайное значение, но сделайте его необязательным, AutoLayout установит высоту точно, чтобы она соответствовала подзонам. (синие стрелки)

Это отлично работает, нет необходимости вызывать дополнительные методы обновления системного макета.