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

Я не могу ради любви к Богу повесить это изменение размера супервизора.

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

Контент во всех 4 динамических исходит из базы данных.

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

Я использую autolayout программно и установил высоту супервизора, равную или превышающую фиктивное число.

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

Мне нужно пересчитать ограничения для супервизора где-то конкретно. Может быть, установить высоту как «@property» в своем классе контроллера, удалить и прочитать ее? Atm Я попытался поставить все везде, а затем и некоторые. Тем не менее я получаю конечный результат того же размера с фиктивной высотой и текстом, плавающим снаружи. Даже после установки clipsToBound в подвиде.

Я чешу волосы.. помогите


person Pedroinpeace    schedule 03.10.2013    source источник
comment
Эй, не могли бы вы разместить свой код где-нибудь на pastebin или что-то в этом роде, если бы я мог взглянуть? Я страдаю от аналогичной проблемы. Прошла неделя или больше.   -  person esh    schedule 18.03.2014


Ответы (4)


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

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

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

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

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

person smileyborg    schedule 05.10.2013
comment
Спасибо смайликборг. Поздний ответ, так как я был в середине проекта и не совсем понял, что вы сказали. Теперь у меня была возможность еще немного поработать с ограничениями программно и особенно с constraintsWithVisualFormat, и я полностью понимаю вашу точку зрения о растягивании содержащихся вложенных представлений и как бы выталкивании суперпредставления до его размера :) Еще раз спасибо - person Pedroinpeace; 01.11.2013
comment
Я согласен с решением, но оно у меня не работает, проверьте stackoverflow.com/questions/34635838/ - person Omer; 06.01.2016
comment
Этот ответ волшебный. Так гораздо меньше усилий с моей стороны, чтобы взгляды выглядели хорошо. - person Chris; 20.04.2016
comment
Следует отметить, что вы должны установить translatesAutoresizingMaskIntoConstraints = NO, если вы используете xib. - person KudoCC; 27.01.2017
comment
translatesAutoresizingMaskIntoConstraints = НЕТ - ответ для моего случая. Но теперь представление контейнера потеряло кадр, и его происхождение всегда (0,0), я не могу поставить его в нужное место. stackoverflow.com/questions/45548372/ - person karim; 07.08.2017
comment
@smileyborg Кажется, это не работает, когда я разрабатываю UIViewController, хранящийся в отдельной раскадровке. Мне пришлось добавить размер моего представления коллекции внутри суперпредставления (представление контроллера), потому что в противном случае представление коллекции было пустым во время выполнения. - person Michele Dall'Agata; 12.08.2018
comment
@smileyborg, это полезный совет, но что, если я хочу иметь ограничение по высоте для своих подвидов? - person Winston Du; 19.07.2020

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

В следующем примере у меня есть изображение 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, который является многострочным

person Cameron Lowell Palmer    schedule 28.01.2014
comment
-UIViewShowAlignmentRects YES -- отличный совет! - person Ralfonso; 21.10.2015
comment
В этом случае контейнер должен только адаптировать свою высоту к этикетке. Что, если контейнер должен адаптироваться к сумме высот более чем одного вида? - person da Rocha Pires; 18.11.2015

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

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

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

view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

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

person Jacob Ruth    schedule 30.08.2016
comment
Я использую StackView и динамически добавляю представления, размеры этих представлений не изменяются. @JacobRuth - person Mansuu....; 06.09.2017

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

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

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

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

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

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

person nsinvocation    schedule 21.09.2017
comment
как сделать высоту необязательной .. Я новичок в iOS, поэтому не могу понять. спасибо - person Faisal Naseer; 30.09.2020