Какао Autolayout: обнимание контента против приоритета сопротивления сжатия контента


643

Я не могу найти четкого ответа на документацию Apple, касающуюся Autolayout Cocoa о разнице между объятием контента и сопротивлением сжатию.

Может кто-нибудь объяснить их обычаи и разницу?


49
Одна из главных загадок жизни - почему они не назвали это просто «Сопротивлением расширению». Эти два качества - не что иное, как «Сопротивление расширению» и «Сопротивление сжатию» . Терминология «обниматься» безумна.
Толстяк

3
Если у вас слишком много места, то вы content-huggingбы боролись с пробелами. Это просто заставит вид обойти вас. Но если у вас не слишком много места и вместо этого очень мало места, content-compressions-resistanceвы будете бороться с тем, что ваш взгляд не может показать весь его контент, например, ярлыки будут обрезаны.
Мед

Ответы:


1319

Краткое резюме понятий:

  • Обниматься => контент не хочет расти
  • Сопротивление сжатию => контент не хочет сжиматься

Пример:

Скажем, у вас есть такая кнопка:

[       Click Me      ]

и вы прикрепили края к большему суперпредставлению с приоритетом 500.

Тогда, если приоритет Hugging> 500, это будет выглядеть так:

[Click Me]

Если приоритет Hugging <500, это будет выглядеть так:

[       Click Me      ]

Если суперпредставление теперь сжимается, если приоритет сопротивления сжатию> 500, это будет выглядеть так

[Click Me]

Иначе, если приоритет сопротивления сжатию <500, он может выглядеть так:

[Cli..]

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

Например, вы можете прикрепить его к суперпредставлению с приоритетом 1000. Или вы можете иметь приоритет ширины. Если это так, это может быть полезно:

Редактор> Размер по размеру содержимого


37
Что если обнять приоритет == 500?
bradley.ayers

1
Я бы предположил (но это, как правило, не очень хорошая идея), что это будет рассматриваться как> 500, как типичное поведение округления. Хотя не проверял это.
Джошуа Ноцци,

скорее всего, во время выполнения вы получите предупреждение «Невозможно одновременно выполнить ограничения»
Макс Десятов,

8
@ bradley.ayers К комментарию MaxDesyatov, это произойдет, только если у вас есть конфликтующие ограничения с Обязательным приоритетом (1000). Если два ограничения с более низким приоритетом конфликтуют, решение неоднозначно, поэтому механизм автоматического размещения просто выберет одно допустимое решение, и это то, что вы увидите (без предупреждений). Очевидно, что это нехорошо, потому что теперь внутренняя реализация механизма Auto Layout должна выбирать, как выглядит ваш макет, и теоретически это может измениться с одной версии iOS на другую!
смайлиборг

По умолчанию приоритет при обнимании контента равен 250, а по умолчанию сопротивление сжатию контента - 750. Так зачем использовать 500?
ZYiOS

292

Взгляните на этот видеоурок об Autolayout , они объясняют это внимательно

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


1
@fatuhoku Вы можете проверить еще раз, это видео бесплатно
onmyway133

31
Обсуждение обниматься против сопротивления начинается примерно в 13:15 в видео.
Карл Смит

1
@ onmyway133 это идеальное видео, но, к сожалению, нет примера, как его использует Рэй.
Матросов Александр

@MatrosovAlexander Я думаю, что очень практичным примером будет динамическая высота ячейки с Autolayout fantageek.com/1468/…
onmyway133

1
Он показывает, как использовать сопротивление сжатию в 18:05
Брент Фауст,

187

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

Источник: @mokagio

Внутренний размер контента. Довольно понятен, но представления с переменным контентом знают, насколько велик их контент, и описывают размер своего контента через это свойство. Некоторыми очевидными примерами представлений с внутренними размерами контента являются UIImageViews, UILabels, UIButtons.

Приоритет размещения контента. Чем выше этот приоритет, тем больше сопротивление представлению становится больше, чем его собственный размер контента.

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

Проверьте здесь для более подробного объяснения: МАГИЯ АВТОМАТИЧЕСКОГО РАЗМЕЩЕНИЯ: ПРИОРИТЕТЫ РАЗМЕРА КОНТЕНТА


Иллюстрация хороша, но, по меньшей мере, вводит в заблуждение. Лучший парень должен сказать: «Я не собираюсь (пусть я) расти». Дочернее представление само по себе определяет, что оно не хочет развиваться через поведение, связанное с содержанием. Не существует экзогенной силы (как на изображенных руках), которая мешает ей расти. Это большая разница.
Мануэль

6
Я голосую за это только потому, что мне нравится иллюстрация.
Джеймс Буканек

3
Вот почему я люблю Stack Overflow… описание Snowcrash и эту иллюстрацию от mokagio = лучшее объяснение этих свойств где угодно (включая собственную документацию Apple).
Кал

40

Допустим, у вас есть кнопка с текстом «Нажмите меня». Какой ширины должна быть эта кнопка?

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

Во-вторых, вы не хотите, чтобы кнопка была больше, чем она должна быть. Кнопка, которая выглядела следующим образом, [Click Me], очевидно, слишком велика. Вы хотите, чтобы кнопка «обнимала» ее содержимое без слишком большого заполнения. Это горизонтальный приоритет содержания контента. Для кнопки это не так сильно, как приоритет сопротивления горизонтальному сжатию.


19

Если view.intrinsicContentSize.width != NSViewNoIntrinsicMetric, тогда автоматическое расположение создает специальное ограничение типа NSContentSizeLayoutConstraint. Это ограничение действует как два нормальных ограничения:

  • ограничение, требующее view.width <= view.intrinsicContentSize.widthс приоритетом горизонтального объятия, и
  • ограничение, требующее view.width >= view.intrinsicContentSize.widthприоритета сопротивления горизонтальному сжатию.

В Swift с новыми привязками макетов в iOS 9 вы можете установить эквивалентные ограничения, например:

let horizontalHugging = view.widthAnchor.constraint(
    lessThanOrEqualToConstant: view.intrinsicContentSize.width)
horizontalHugging.priority = view.contentHuggingPriority(for: .horizontal)

let horizontalCompression = view.widthAnchor.constraint(
    greaterThanOrEqualToConstant: view.intrinsicContentSize.width)
horizontalCompression.priority = view.contentCompressionResistancePriority(for: .horizontal)

Точно так же, если view.intrinsicContentSize.height != NSViewNoIntrinsicMetric, тогда автоматическое расположение создает, NSContentSizeLayoutConstraintкоторый действует как два ограничения на высоту представления. В коде они будут выглядеть так:

let verticalHugging = view.heightAnchor.constraint(
    lessThanOrEqualToConstant: view.intrinsicContentSize.height)
verticalHugging.priority = view.contentHuggingPriority(for: .vertical)

let verticalCompression = view.heightAnchor.constraint(
    greaterThanOrEqualToConstant: view.intrinsicContentSize.height)
verticalCompression.priority = view.contentCompressionResistancePriority(for: .vertical)

Вы можете увидеть эти особые NSContentSizeLayoutConstraintэкземпляры (если они существуют), напечатав view.constraintsпосле запуска макета. Пример:

label.constraints.forEach { print($0) }

// Output:
<NSContentSizeLayoutConstraint:0x7fd82982af90 H:[UILabel:0x7fd82980e5e0'Hello'(39)] Hug:250 CompressionResistance:750>
<NSContentSizeLayoutConstraint:0x7fd82982b4f0 V:[UILabel:0x7fd82980e5e0'Hello'(21)] Hug:250 CompressionResistance:750>

1
не должно быть: let verticalCompression = view.heightAnchor.constraint (moreThanOrEqualToConstant: view.intrinsicContentSize.height)
mc_plectrum

1
Да, я сделал ошибку копирования / вставки. Я исправил это. Спасибо, что сообщили мне об этом.
Роб Майофф

15

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

Из документов Apple :

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


plus1 для изображения (Y)
Нур Али Батт

Я смущен. Для textView, у которого не включена прокрутка. Значит ли это, что для каждого пользователя, набравшего собственный размер, изменится?
Мед

@ Мед, я думаю, с правильными установленными ограничениями и отключенной прокруткой, текстовое представление должно иметь возможность определить внутреннюю высоту.
Dev Gr

Это не ответило на мой вопрос. Вы имеете в виду, если я много набираю, больше, чем текущий размер textView .... автоматически ли textView расширяется и изменяет внутренний размер?
Мед

Попробуй сам. Присвойте textview фиксированную ширину, отключите прокрутку и проверьте желаемое поведение. Обратитесь к stackoverflow.com/a/21287306/1526629 для получения дополнительных ответов.
Dev Gr

11

Это Content hugging priorityкак резиновая полоса, которая размещается вокруг вида. Чем выше значение приоритета, тем сильнее резиновая полоса и тем больше она хочет обнять свой размер содержимого. Значение приоритета можно представить как «прочность» резиновой ленты

И Content Compression Resistanceэто то, насколько представление «сопротивляется» уменьшению . Представление с более высоким значением приоритета сопротивления будет сопротивляться сжатию.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.