Cocoa Autolayout: memeluk konten vs prioritas resistensi kompresi konten


643

Saya tidak dapat menemukan jawaban yang jelas pada dokumentasi Apple mengenai Cocoa Autolayout tentang perbedaan antara pelukan konten dan resistensi kompresi.

Adakah yang bisa menjelaskan penggunaan dan perbedaan mereka?


49
Salah satu misteri utama kehidupan adalah mengapa mereka tidak menyebutnya sebagai "Perlawanan Ekspansi". Kedua kualitas itu tidak lebih dari "Perlawanan Ekspansi" dan "Perlawanan Kompresi" . Terminologi "pelukan" itu gila.
Fattie

3
Jika Anda memiliki terlalu banyak ruang maka content-hugging: akan berjuang melawan memiliki ruang putih. Itu hanya akan memaksa pandangan untuk berkeliling Anda. Tetapi jika Anda tidak memiliki terlalu banyak ruang, dan sebaliknya memiliki tempat yang sangat sedikit maka content-compressions-resistanceakan melawan pandangan Anda karena tidak dapat menampilkan semua kontennya, misalnya label akan terpotong.
Sayang

Jawaban:


1319

Ringkasan singkat konsep:

  • Memeluk => konten tidak ingin tumbuh
  • Perlawanan kompresi => konten tidak ingin menyusut

Contoh:

Katakanlah Anda memiliki tombol seperti ini:

[       Click Me      ]

dan Anda telah menyematkan tepi pada superview yang lebih besar dengan prioritas 500.

Kemudian, jika prioritas Memeluk> 500 akan terlihat seperti ini:

[Click Me]

Jika Memeluk prioritas <500 akan terlihat seperti ini:

[       Click Me      ]

Jika superview sekarang menyusut maka, jika prioritas Perlawanan Kompresi> 500, itu akan terlihat seperti ini

[Click Me]

Atau jika prioritas Perlawanan Kompresi <500, itu bisa terlihat seperti ini:

[Cli..]

Jika tidak bekerja seperti ini, maka Anda mungkin memiliki beberapa kendala lain yang mengacaukan pekerjaan baik Anda!

Misalnya Anda bisa menyematkannya ke superview dengan prioritas 1000. Atau Anda dapat memiliki prioritas lebar. Jika demikian, ini dapat membantu:

Editor> Ukuran untuk Menyesuaikan Konten


37
Bagaimana jika memeluk prioritas == 500?
bradley.ayers

1
Saya berasumsi (tapi itu biasanya bukan ide yang baik) itu akan diperlakukan sebagai> 500 seperti perilaku pembulatan khas. Belum diuji itu.
Joshua Nozzi

kemungkinan besar Anda akan mendapatkan peringatan "Tidak dapat memenuhi kendala secara bersamaan" dalam runtime
Max Desiatov

8
@ bradley.ayers Untuk komentar MaxDesyatov, itu hanya akan terjadi jika Anda memiliki kendala yang bertentangan dengan prioritas yang Diperlukan (1000). Jika dua kendala kendala prioritas rendah, solusinya ambigu sehingga mesin Tata Letak Otomatis hanya akan memilih satu solusi yang valid dan itulah yang akan Anda lihat (tidak ada peringatan). Jelas ini tidak baik, karena sekarang tergantung pada implementasi internal mesin Auto Layout untuk memilih bagaimana tampilan layout Anda, dan secara teoritis ini dapat berubah dari satu versi iOS ke yang berikutnya!
smileyborg

Default prioritas memeluk konten adalah 250, dan standar resistensi kompresi konten adalah 750. Jadi mengapa menggunakan 500?
ZYiOS

292

Lihatlah tutorial video ini tentang Autolayout , mereka menjelaskannya dengan cermat

masukkan deskripsi gambar di sini


1
@fatuhoku dapat Anda periksa lagi, video ini gratis
onmyway133

31
Diskusi memeluk vs Perlawanan dimulai pada sekitar titik 13:15 dalam video.
Carl Smith

1
@ onmyway133 ini adalah video yang sempurna, tapi sayangnya tidak ada contoh bagaimana Ray menggunakannya.
Matrosov Alexander

@MatrosovAlexander Saya pikir contoh yang sangat praktis adalah tinggi sel dinamis dengan Autolayout fantageek.com/1468/…
onmyway133

1
Dia menunjukkan cara menggunakan resistensi kompresi pada 18:05
Brent Faust

187

masukkan deskripsi gambar di sini

sumber: @mokagio

Ukuran Konten Intrinsik - Cukup jelas, tetapi pandangan dengan konten variabel menyadari seberapa besar konten mereka dan menggambarkan ukuran konten mereka melalui properti ini. Beberapa contoh nyata dari tampilan yang memiliki ukuran konten intrinsik adalah UIImageViews, UILabels, UIButtons.

Prioritas Memeluk Konten - Semakin tinggi prioritas ini, semakin banyak yang menolak semakin besar ukuran konten intrinsiknya.

Prioritas Ketahanan Kompresi Konten - Semakin tinggi prioritas ini, semakin banyak pandangan yang menolak menyusut lebih kecil dari ukuran konten intrinsiknya.

Periksa di sini untuk penjelasan lebih lanjut: AUTO LAYOUT MAGIC: PRIORITAS UKURAN KONTEN


Ilustrasi itu bagus tetapi menyesatkan untuk sedikitnya. Cowok top harus mengatakan "Aku tidak akan (biarkan AKU) tumbuh". Pandangan anak mendefinisikan sendiri bahwa ia tidak ingin tumbuh melalui perilaku memeluk konten itu. Tidak ada kekuatan eksogen (seperti tangan yang diilustrasikan) yang menghentikannya tumbuh. Itu merupakan perbedaan besar.
Manuel

6
Saya memilih ini hanya karena saya suka ilustrasinya.
James Bucanek

3
Inilah sebabnya saya suka Stack Overflow ... Deskripsi Snowcrash plus ilustrasi ini oleh mokagio = penjelasan terbaik tentang properti ini di mana saja (termasuk dokumentasi Apple sendiri).
Kal

40

Katakanlah Anda memiliki tombol dengan teks, "Klik Saya". Berapa lebar tombol itu?

Pertama, Anda tentu tidak ingin tombolnya lebih kecil dari teks. Jika tidak, teks akan terpotong. Ini adalah prioritas ketahanan kompresi horisontal.

Kedua, Anda tidak ingin tombolnya menjadi lebih besar dari yang seharusnya. Sebuah tombol yang terlihat seperti ini, [Klik Saya], jelas terlalu besar. Anda ingin tombol "memeluk" isinya tanpa terlalu banyak bantalan. Ini adalah prioritas memeluk konten horisontal. Untuk sebuah tombol, itu tidak sekuat prioritas ketahanan kompresi horisontal.


19

Jika view.intrinsicContentSize.width != NSViewNoIntrinsicMetric, maka tata letak otomatis menciptakan batasan tipe khusus NSContentSizeLayoutConstraint. Batasan ini bertindak seperti dua batasan normal:

  • kendala yang membutuhkan view.width <= view.intrinsicContentSize.widthdengan prioritas memeluk horisontal, dan
  • kendala yang diperlukan view.width >= view.intrinsicContentSize.widthdengan prioritas ketahanan kompresi horisontal.

Di Swift, dengan jangkar tata letak baru iOS 9, Anda dapat mengatur batasan yang setara seperti ini:

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)

Demikian pula, jika view.intrinsicContentSize.height != NSViewNoIntrinsicMetric, maka tata letak otomatis membuat NSContentSizeLayoutConstraintyang bertindak seperti dua kendala pada ketinggian tampilan. Dalam kode, mereka akan terlihat seperti ini:

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)

Anda dapat melihat NSContentSizeLayoutConstraintcontoh khusus ini (jika ada) dengan mencetak view.constraintssetelah tata letak telah berjalan. Contoh:

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
seharusnya tidak menjadi: biarkan verticalCompression = view.heightAnchor.constraint (GreaterThanOrEqualToConstant: view.intrinsicContentSize.height)
mc_plectrum

1
Ya, saya membuat kesalahan salin / tempel. Saya sudah memperbaikinya. Terima kasih telah memberitahu saya.
rob mayoff

15

Memeluk Konten dan Prioritas Ketahanan Kompresi Konten berfungsi untuk elemen yang dapat menghitung ukurannya secara intrinsik tergantung pada konten yang masuk.

Dari dokumen Apple :

masukkan deskripsi gambar di sini


plus1 untuk gambar (Y)
Noor Ali Butt

Saya bingung. Untuk textView yang gulirnya tidak diaktifkan. Apakah itu berarti per pengguna mengetik ukuran intrinsik akan berubah?
Sayang

@ Madu Saya pikir dengan batasan yang benar ditetapkan dan bergulir dinonaktifkan, tampilan teks harus bisa mengatakan ketinggian intrinsik.
dev gr

Itu tidak menjawab pertanyaan saya. Maksud Anda jika saya mengetik banyak, lebih dari ukuran textView saat ini .... apakah textView berkembang secara otomatis dan mengubah ukuran intrinsik?
Sayang

Cobalah sendiri. Berikan tampilan teks lebar tetap dan nonaktifkan gulir dan periksa perilaku yang diinginkan. Rujuk stackoverflow.com/a/21287306/1526629 untuk lebih banyak jawaban.
dev gr

11

Itu Content hugging priorityseperti karet gelang yang ditempatkan di sekitar tampilan. Semakin tinggi nilai prioritas, semakin kuat karet gelang dan semakin banyak yang ingin dipeluk dengan ukuran kontennya. Nilai prioritas dapat dibayangkan seperti "kekuatan" karet gelang

Dan Content Compression Resistance, berapa banyak tampilan "menolak" semakin kecil Tampilan dengan nilai prioritas resistensi yang lebih tinggi adalah yang akan menolak kompresi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.