Cocoa Autolayout: Priorität zwischen Inhalt und Komprimierungsbeständigkeit

643

Ich kann in der Apple-Dokumentation zu Cocoa Autolayout keine eindeutige Antwort auf den Unterschied zwischen Inhaltsumarmung und Komprimierungsbeständigkeit finden.

Kann jemand ihre Verwendung und ihren Unterschied erklären?

dmitrynikolaev
quelle
49
Eines der größten Rätsel des Lebens ist, warum sie es nicht einfach "Expansionswiderstand" nannten. Die beiden Eigenschaften sind nichts anderes als "Expansionsbeständigkeit" und "Kompressionsbeständigkeit" . Die "umarmende" Terminologie ist verrückt.
Fattie
3
Wenn Sie zu viel Platz haben, dann content-hugging: würden Sie gegen Leerzeichen kämpfen. Es würde nur den Blick zwingen, um dich herumzukommen. Aber wenn Sie nicht zu viel Platz haben, und stattdessen haben sehr wenig Platz dann content-compressions-resistancegegen Ihre Ansicht kämpfen würde aus nicht in der Lage sind , alle seine Inhalte zu zeigen, zB Etiketten würden abgeschnitten bekommen.
Honig

Antworten:

1319

Eine kurze Zusammenfassung der Konzepte:

  • Umarmen => Inhalt will nicht wachsen
  • Kompressionswiderstand => Inhalt möchte nicht verkleinert werden

Beispiel:

Angenommen, Sie haben eine Schaltfläche wie diese:

[       Click Me      ]

und Sie haben die Kanten an eine größere Übersicht mit Priorität 500 angeheftet.

Wenn dann die Umarmungspriorität> 500 ist, sieht es folgendermaßen aus:

[Click Me]

Wenn die Umarmungspriorität <500 ist, sieht es so aus:

[       Click Me      ]

Wenn die Übersicht jetzt verkleinert wird und die Priorität für den Komprimierungswiderstand> 500 ist, sieht dies folgendermaßen aus

[Click Me]

Andernfalls könnte die Kompressionswiderstandspriorität <500 folgendermaßen aussehen:

[Cli..]

Wenn es so nicht funktioniert, haben Sie wahrscheinlich einige andere Einschränkungen, die Ihre gute Arbeit durcheinander bringen!

Sie könnten es beispielsweise mit der Priorität 1000 an die Übersicht anheften lassen. Oder Sie könnten eine Breitenpriorität haben. Wenn ja, kann dies hilfreich sein:

Editor> Größe an Inhalt anpassen

Snowcrash
quelle
37
Was ist, wenn Priorität == 500?
Bradley.ayers
1
Ich würde annehmen (aber das ist normalerweise keine gute Idee), dass es wie ein typisches Rundungsverhalten als> 500 behandelt wird. Habe das aber nicht getestet.
Joshua Nozzi
Höchstwahrscheinlich erhalten Sie zur Laufzeit die Warnung "Einschränkungen können nicht gleichzeitig erfüllt werden"
Max Desiatov,
8
@ bradley.ayers Laut MaxDesyatovs Kommentar geschieht dies nur, wenn Sie widersprüchliche Einschränkungen mit der erforderlichen Priorität (1000) haben. Wenn zwei Einschränkungen mit niedrigerer Priorität in Konflikt stehen, ist die Lösung nicht eindeutig, sodass die Auto-Layout-Engine nur eine gültige Lösung auswählt. Dies wird angezeigt (keine Warnungen). Offensichtlich ist dies nicht gut, da es nun an der internen Implementierung der Auto-Layout-Engine liegt, zu entscheiden, wie Ihr Layout aussieht, und theoretisch könnte sich dies von einer iOS-Version zur nächsten ändern!
Smileyborg
Die Standardeinstellung für die Inhaltsumarmung ist 250 und die Standardeinstellung für die Komprimierungsbeständigkeit von Inhalten ist 750. Warum also 500 verwenden?
ZYiOS
292

Schauen Sie sich dieses Video- Tutorial über Autolayout an , sie erklären es sorgfältig

Geben Sie hier die Bildbeschreibung ein

onmyway133
quelle
1
@ Fatuhoku können Sie noch einmal überprüfen, dieses Video ist kostenlos
onmyway133
31
Die Diskussion zwischen Umarmen und Widerstand beginnt ungefähr um 13:15 Uhr im Video.
Carl Smith
1
@ onmyway133 das ist ein perfektes Video, aber leider gibt es kein Beispiel, wie Ray es benutzt.
Matrosov Alexander
@ MatrosovAlexander Ich denke, ein sehr praktisches Beispiel wäre die dynamische Zellenhöhe mit Autolayout fantastageek.com/1468/…
onmyway133
1
Er zeigt, wie man den Kompressionswiderstand um 18:05 Uhr verwendet
Brent Faust
187

Geben Sie hier die Bildbeschreibung ein

Quelle: @mokagio

Größe des eigentlichen Inhalts Inhaltsgröße - Ziemlich selbsterklärend, aber Ansichten mit variablem Inhalt wissen, wie groß ihr Inhalt ist, und beschreiben die Größe ihres Inhalts über diese Eigenschaft. Einige offensichtliche Beispiele für Ansichten mit intrinsischen Inhaltsgrößen sind UIImageViews, UILabels, UIButtons.

Priority Hugging Priority - Je höher diese Priorität ist, desto mehr kann eine Ansicht nicht größer werden als ihre eigentliche Inhaltsgröße.

Widerstandspriorität für die Komprimierung von Inhalten - Je höher diese Priorität ist, desto mehr widersteht eine Ansicht dem Verkleinern, das kleiner als ihre eigentliche Inhaltsgröße ist.

Weitere Erklärungen finden Sie hier: AUTO LAYOUT MAGIC: PRIORITÄTEN FÜR DIE INHALTSGRÖSSE

Balasubramanian
quelle
Die Illustration ist nett, aber gelinde gesagt irreführend. Der Top-Typ sollte sagen "Ich werde nicht (lass MICH) wachsen". Die untergeordnete Ansicht definiert von sich aus, dass sie nicht durch ihr inhaltsumarmendes Verhalten wachsen möchte. Es gibt keine exogene Kraft (wie die abgebildeten Hände), die das Wachstum verhindert. Das ist ein großer Unterschied.
Manuel
6
Ich stimme darüber ab, nur weil ich die Illustration liebe.
James Bucanek
3
Aus diesem Grund liebe ich Stack Overflow… Snowcrashs Beschreibung plus diese Illustration von mokagio = beste Erklärung dieser Eigenschaften überall (einschließlich Apples eigener Dokumentation).
Kal
40

Angenommen, Sie haben eine Schaltfläche mit dem Text "Click Me". Welche Breite sollte dieser Knopf haben?

Erstens möchten Sie definitiv nicht, dass die Schaltfläche kleiner als der Text ist. Andernfalls würde der Text abgeschnitten. Dies ist die Priorität des horizontalen Kompressionswiderstands.

Zweitens möchten Sie nicht, dass die Schaltfläche größer ist, als sie sein muss. Eine Schaltfläche, die so aussah, [Click Me], ist offensichtlich zu groß. Sie möchten, dass die Schaltfläche ihren Inhalt ohne zu viel Polsterung "umarmt". Dies ist die Priorität des horizontalen Inhalts. Für eine Schaltfläche ist sie nicht so stark wie die Priorität für den horizontalen Kompressionswiderstand.

Bridger Maxwell
quelle
19

Wenn view.intrinsicContentSize.width != NSViewNoIntrinsicMetric, dann erstellt das automatische Layout eine spezielle Einschränkung des Typs NSContentSizeLayoutConstraint. Diese Einschränkung wirkt wie zwei normale Einschränkungen:

  • eine Einschränkung, die view.width <= view.intrinsicContentSize.widthmit der horizontalen Umarmungspriorität erfordert , und
  • eine Einschränkung erforderlich view.width >= view.intrinsicContentSize.width mit der Priorität des horizontalen Kompressionswiderstands .

In Swift können Sie mit den neuen Layout-Ankern von iOS 9 entsprechende Einschränkungen festlegen:

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)

In ähnlicher Weise wird beim view.intrinsicContentSize.height != NSViewNoIntrinsicMetricautomatischen Layout ein Layout erstellt NSContentSizeLayoutConstraint, das sich wie zwei Einschränkungen für die Höhe der Ansicht verhält. Im Code würden sie so aussehen:

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)

Sie können diese speziellen NSContentSizeLayoutConstraintInstanzen (falls vorhanden) anzeigen, indem Sie view.constraintsnach dem Ausführen des Layouts drucken . Beispiel:

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>
Rob Mayoff
quelle
1
sollte es nicht sein: let vertikalCompression = view.heightAnchor.constraint (GreaterThanOrEqualToConstant: view.intrinsicContentSize.height)
mc_plectrum
1
Ja, ich habe einen Kopier- / Einfügefehler gemacht. Ich habe es korrigiert. Danke, dass Sie mich informiert haben.
Rob Mayoff
15

Die Prioritäten für das Umarmen von Inhalten und die Beständigkeit gegen Komprimierung von Inhalten gelten für Elemente, deren Größe abhängig von den eingehenden Inhalten berechnet werden kann.

Aus Apple-Dokumenten :

Geben Sie hier die Bildbeschreibung ein

dev gr
quelle
plus1 für das Bild (Y)
Noor Ali Butt
Ich bin verwirrt. Für eine Textansicht, für die kein Bildlauf aktiviert ist. Bedeutet das, dass sich pro Benutzer die Eingabe der intrinsischen Größe ändern würde?
Honey
@Honey Ich denke, wenn die richtigen Einschränkungen festgelegt und das Scrollen deaktiviert sind, sollte die Textansicht in der Lage sein, die innere Höhe zu bestimmen.
dev gr
Das hat meine Frage nicht beantwortet. Sie meinen, wenn ich viel tippe, mehr als die aktuelle Größe der Textansicht ... wird die Textansicht automatisch erweitert und ändert sich die intrinsische Größe?
Honig
Versuch es selber. Geben Sie der Textansicht eine feste Breite, deaktivieren Sie den Bildlauf und überprüfen Sie das gewünschte Verhalten. Weitere Antworten finden Sie unter stackoverflow.com/a/21287306/1526629 .
dev gr
11

Das Content hugging priorityist wie ein Gummiband , das um eine Ansicht gelegt wird. Je höher der Prioritätswert, desto stärker das Gummiband und desto mehr möchte es an seine Inhaltsgröße anpassen. Der Prioritätswert kann wie die "Stärke" des Gummibands vorgestellt werden

Und das Content Compression Resistanceheißt, wie sehr sich eine Ansicht "widersetzt", kleiner zu werden. Die Ansicht mit dem höheren Widerstandsprioritätswert ist diejenige, die der Komprimierung widersteht.

Naishta
quelle