Automatyczne układanie kakao: przytulanie treści a priorytet odporności na kompresję treści


643

Nie mogę znaleźć jednoznacznej odpowiedzi w dokumentacji Apple dotyczącej autoukładu Cocoa o różnicy między przytulaniem treści a odpornością na kompresję.

Czy ktoś może wyjaśnić ich zwyczaje i różnice?


49
Jednym z głównych zagadek życia jest to, dlaczego nie nazwali tego po prostu „Odpornością na ekspansję”. Te dwie cechy to nic innego jak „odporność na rozszerzanie się” i „odporność na ściskanie” . Termin „przytulanie” jest szalony.
Fattie

3
Jeśli masz za dużo miejsca, to content-hugging: walczyłby z pustą przestrzenią. Zmusiłoby to widok do obejścia ciebie. Ale jeśli nie masz za dużo miejsca, a zamiast tego masz bardzo mało miejsca, wówczas content-compressions-resistancewalczyłbyś z twoim widokiem, ponieważ nie był w stanie wyświetlić całej jego zawartości, np. Etykiety zostałyby obcięte.
Honey

Odpowiedzi:


1319

Szybkie podsumowanie pojęć:

  • Przytulanie => treść nie chce się rozwijać
  • Odporność na ściskanie => zawartość nie chce się kurczyć

Przykład:

Powiedz, że masz taki przycisk:

[       Click Me      ]

i przypiąłeś krawędzie do większego podglądu z priorytetem 500.

Następnie, jeśli Priorytet przytulania> 500 będzie wyglądał następująco:

[Click Me]

Jeśli priorytet przytulania <500 będzie wyglądał następująco:

[       Click Me      ]

Jeśli superwizja teraz się zmniejszy, to jeśli priorytet Odporności na ściskanie> 500, będzie to wyglądać tak

[Click Me]

W przeciwnym razie, jeśli priorytet odporności na ściskanie wynosi <500, może wyglądać następująco:

[Cli..]

Jeśli to nie działa tak, prawdopodobnie masz jakieś inne ograniczenia, które psują twoją dobrą pracę!

Np. Możesz przypiąć go do superwizji z priorytetem 1000. Lub możesz mieć priorytet szerokości. Jeśli tak, może to być pomocne:

Edytor> Dopasuj rozmiar do treści


37
Co jeśli priorytet obejmuje przytulanie == 500?
bradley.ayers

1
Chciałbym założyć, (ale to nie jest zwykle dobrym pomysłem) by go traktować jako> 500 jak typowe zachowania zaokrąglania. Jednak tego nie testowałem.
Joshua Nozzi

najprawdopodobniej
pojawi się

8
@ bradley.ayers Do komentarza MaxDesyatova stanie się to tylko wtedy, gdy będziesz mieć sprzeczne ograniczenia o wymaganym priorytecie (1000). W przypadku konfliktu dwóch ograniczeń o niższym priorytecie rozwiązanie jest niejednoznaczne, więc silnik Auto Layout wybierze tylko jedno prawidłowe rozwiązanie i właśnie to zobaczysz (bez ostrzeżeń). Oczywiście nie jest to dobre, ponieważ teraz to od wewnętrznej implementacji silnika Auto Layout zależy, jak będzie wyglądać twój układ, i teoretycznie może to zmienić się z jednej wersji iOS na drugą!
Smileyborg

Domyślnym priorytetem przytulania treści jest 250, a domyślnym poziomem odporności na kompresję 750. Po co więc używać 500?
ZYiOS 15.04.15

292

Rzuć okiem na ten film instruktażowy na temat Autolayout , wyjaśniają go dokładnie

wprowadź opis zdjęcia tutaj


1
@fatuhoku, czy możesz sprawdzić ponownie, ten film jest bezpłatny
onmyway133

31
Dyskusja na temat przytulania a oporu rozpoczyna się około 13:15 w filmie.
Carl Smith,

1
@ onmyway133 jest to idealny film, ale niestety nie ma przykładu, w jaki sposób Ray go używa.
Matrosov Alexander

@MatrosovAlexander Myślę, że bardzo praktycznym przykładem byłaby dynamiczna wysokość komórki z Autolayout fantageek.com/1468/…
onmyway133

1
Pokazuje, jak używać oporu kompresji o 18:05
Brent Faust

187

wprowadź opis zdjęcia tutaj

źródło: @mokagio

Rozmiar zawartości wewnętrznej - dość oczywisty, ale widoki ze zmienną zawartością są świadome, jak duża jest ich zawartość i opisują rozmiar zawartości za pomocą tej właściwości. Niektórymi oczywistymi przykładami widoków, które mają rzeczywiste rozmiary treści, są UIImageViews, UILabels, UIButtons.

Priorytet przytulania zawartości - im wyższy jest ten priorytet, tym bardziej widok jest odporny na powiększanie się niż jego rozmiar.

Priorytet odporności na kompresję treści - im wyższy jest ten priorytet, tym bardziej widok jest mniejszy niż jego rzeczywisty rozmiar.

Sprawdź tutaj, aby uzyskać więcej wyjaśnień: MAGIA AUTOMATYCZNEGO UKŁADANIA: PRIORYTETY ROZMIARU TREŚCI


Ilustracja jest ładna, ale co najmniej myląca. Najwyższy facet powinien powiedzieć: „Nie zamierzam (pozwolić MNIE) urosnąć”. Widok potomny sam określa, że ​​nie chce się rozwijać dzięki zachowaniu polegającemu na przytulaniu treści. Nie ma siły egzogennej (jak na ilustrowanych dłoniach), która powstrzymywałaby jej wzrost. To duża różnica.
Manuel

6
Głosuję za tym tylko dlatego, że uwielbiam tę ilustrację.
James Bucanek

3
Właśnie dlatego uwielbiam przepełnienie stosu… Opis Snowcrash plus ta ilustracja autorstwa mokagio = najlepsze wyjaśnienie tych właściwości w dowolnym miejscu (w tym własna dokumentacja Apple).
Kal

40

Załóżmy, że masz przycisk z tekstem „Kliknij mnie”. Jaka powinna być szerokość tego przycisku?

Po pierwsze, zdecydowanie nie chcesz, aby przycisk był mniejszy niż tekst. W przeciwnym razie tekst zostałby obcięty. Jest to priorytet poziomej odporności na ściskanie.

Po drugie, nie chcesz, aby przycisk był większy niż powinien. Przycisk, który wyglądał tak, [Click Me], jest oczywiście zbyt duży. Chcesz, aby przycisk „przytulił” jego zawartość bez zbytniego dopełniania. Jest to horyzontalny poziom przytulania treści. W przypadku przycisku nie jest on tak silny, jak pozioma odporność na kompresję w poziomie.


19

Jeśli view.intrinsicContentSize.width != NSViewNoIntrinsicMetric, to układ automatyczny tworzy specjalne ograniczenie typu NSContentSizeLayoutConstraint. To ograniczenie działa jak dwa normalne ograniczenia:

  • ograniczenie wymagające view.width <= view.intrinsicContentSize.width priorytetu poziomego przytulania, oraz
  • ograniczenie wymagające view.width >= view.intrinsicContentSize.widthpriorytetu poziomej odporności na ściskanie.

W Swift, dzięki nowym kotwicom układu w iOS 9, możesz skonfigurować równoważne ograniczenia takie jak to:

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)

Podobnie jeśli view.intrinsicContentSize.height != NSViewNoIntrinsicMetric, to układ automatyczny tworzy taki, NSContentSizeLayoutConstraintktóry działa jak dwa ograniczenia na wysokości widoku. W kodzie wyglądałyby tak:

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)

Możesz zobaczyć te specjalne NSContentSizeLayoutConstraintwystąpienia (jeśli istnieją), drukując view.constraintspo uruchomieniu układu. Przykład:

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
nie powinno być: niech verticalCompression = view.heightAnchor.constraint (greaterThanOrEqualToConstant: view.intrinsicContentSize.height)
mc_plectrum

1
Tak, popełniłem błąd kopiowania / wklejania. Poprawiłem to. Dziękuję za informację.
rob mayoff

15

Przytulanie zawartości i priorytety odporności na kompresję treści działają dla elementów, które mogą obliczać swój rozmiar wewnętrznie w zależności od nadchodzących treści.

Z dokumentów Apple :

wprowadź opis zdjęcia tutaj


plus 1 za zdjęcie (Y)
Noor Ali Butt

Jestem zmieszany. Dla textView, który nie ma włączonego przewijania. Czy to oznacza, że ​​użytkownik wpisujący wewnętrzny rozmiar by się zmienił?
Kochanie,

@Honey Myślę, że przy ustawionych prawidłowych ograniczeniach i wyłączonym przewijaniu widok tekstu powinien być w stanie określić wewnętrzną wysokość.
dev gr

To nie odpowiedziało na moje pytanie. Masz na myśli to, że jeśli dużo piszę, więcej niż aktualny rozmiar textView ... Czy textView rozwija się automatycznie i zmienia rozmiar wewnętrzny?
Honey,

Spróbuj sam. Nadaj tekstowi stałą szerokość, wyłącz przewijanie i sprawdź pożądane zachowanie. Więcej odpowiedzi można znaleźć na stronie stackoverflow.com/a/21287306/1526629 .
dev gr

11

To Content hugging priorityjest jak gumka która jest umieszczona wokół widoku. Im wyższa wartość priorytetu, tym silniejsza gumka i tym bardziej chce ona przytulić się do swojej zawartości. Wartość priorytetową można sobie wyobrazić jako „siłę” gumki

I o Content Compression Resistanceto, jak bardzo widok „opiera się” zmniejszaniu Widok o wyższej wartości priorytetu odporności jest tym, który będzie odporny na kompresję.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.