Cocoa Autolayout: การแฮ็กเนื้อหากับการจัดลำดับความสำคัญความต้านทานการบีบอัดเนื้อหา


643

ฉันไม่พบคำตอบที่ชัดเจนในเอกสารของ Apple เกี่ยวกับ Cocoa Autolayout เกี่ยวกับความแตกต่างระหว่างการกอดเนื้อหาและการต่อต้านการบีบอัด

ใครสามารถอธิบายประเพณีและความแตกต่างได้บ้าง


49
หนึ่งในความลึกลับที่สำคัญของชีวิตคือเหตุผลที่พวกเขาไม่เรียกมันว่า "การต่อต้านการขยายตัว" ทั้งสองมีคุณสมบัติอะไรมากไปกว่า"การขยายตัวต้านทาน" และ "การบีบอัดต้านทาน" คำศัพท์ "กอด" นั้นบ้า
Fattie

3
หากคุณมีพื้นที่มากเกินไปcontent-hugging: จะต่อสู้กับการมีพื้นที่สีขาว มันแค่บังคับมุมมองที่จะรับรอบตัวคุณ แต่ถ้าคุณไม่มีพื้นที่มากเกินไปและมีที่เล็ก ๆ น้อย ๆ แทนที่จะcontent-compressions-resistanceต่อสู้กับความคิดเห็นของคุณไม่สามารถแสดงเนื้อหาทั้งหมดได้เช่นป้ายกำกับจะถูกตัดทอน
ฮันนี่

คำตอบ:


1319

สรุปแนวคิดรวบยอดอย่างรวดเร็ว:

  • Hugging => เนื้อหาไม่ต้องการเติบโต
  • ความต้านทานแรงอัด => เนื้อหาไม่ต้องการหดตัว

ตัวอย่าง:

สมมติว่าคุณมีปุ่มแบบนี้:

[       Click Me      ]

และคุณได้ปักหมุดขอบไว้ที่จุดกำกับดูแลที่ใหญ่กว่าโดยมีลำดับความสำคัญ 500

จากนั้นหากลำดับความสำคัญ> 500 จะมีลักษณะดังนี้:

[Click Me]

หากการจัดลำดับความสำคัญ <500 จะมีลักษณะดังนี้:

[       Click Me      ]

หากตอนนี้ผู้ดูแลลดขนาดลงหากลำดับความสำคัญในการต้านทานการบีบอัด> 500 จะมีลักษณะเช่นนี้

[Click Me]

มิฉะนั้นหากความสำคัญในการต้านทานการบีบอัด <500 มันอาจมีลักษณะเช่นนี้:

[Cli..]

ถ้ามันไม่ได้ผลแบบนี้คุณอาจมีข้อ จำกัด อื่น ๆ เกิดขึ้นซึ่งทำให้งานของคุณยุ่งเหยิง!

เช่นคุณสามารถตรึงมันไว้กับผู้ดูแลโดยให้ความสำคัญ 1,000 หรือคุณอาจให้ความสำคัญกับความกว้าง ถ้าเป็นเช่นนั้นสิ่งนี้จะเป็นประโยชน์:

ตัวแก้ไข> ขนาดเพื่อให้พอดีกับเนื้อหา


37
เกิดอะไรขึ้นถ้าลำดับความสำคัญ == 500
bradley.ayers

1
ฉันคิดว่า (แต่โดยทั่วไปไม่ใช่ความคิดที่ดี) มันจะได้รับการปฏิบัติเหมือน> 500 เช่นพฤติกรรมการปัดเศษทั่วไป ยังไม่ได้ทดสอบว่า
Joshua Nozzi

เป็นไปได้ว่าคุณจะได้รับคำเตือน "ไม่สามารถตอบสนองข้อ จำกัด " พร้อมกันในรันไทม์
Max Desiatov

8
@ bradley.ayers ถึงความคิดเห็นของ MaxDesyatov ที่จะเกิดขึ้นเฉพาะเมื่อคุณมีข้อ จำกัด ที่ขัดแย้งกับลำดับความสำคัญที่จำเป็น (1,000) หากข้อ จำกัด ที่มีลำดับความสำคัญต่ำกว่าขัดแย้งกันโซลูชันนั้นคลุมเครือดังนั้นกลไกเลย์เอาต์อัตโนมัติจะเลือกโซลูชันที่ถูกต้องหนึ่งรายการเท่านั้นและนั่นคือสิ่งที่คุณจะเห็น (ไม่มีคำเตือน) เห็นได้ชัดว่าสิ่งนี้ไม่ดีเพราะตอนนี้มันขึ้นอยู่กับการใช้งานภายในของเครื่องมือเลย์เอาต์อัตโนมัติเพื่อเลือกว่าเลย์เอาต์ของคุณมีลักษณะอย่างไรและในทางทฤษฎีแล้วสิ่งนี้สามารถเปลี่ยนจาก iOS เวอร์ชันหนึ่งเป็นเวอร์ชันถัดไป!
smileyborg

ค่าเริ่มต้นของการแฮ็กเนื้อหาสำคัญคือ 250 และค่าความต้านทานการบีบอัดเนื้อหาเริ่มต้นคือ 750 ดังนั้นทำไมจึงใช้ 500
ZYiOS

292

ดูวิดีโอแนะนำเกี่ยวกับ Autolayoutพวกเขาอธิบายอย่างระมัดระวัง

ป้อนคำอธิบายรูปภาพที่นี่


1
@fatuhoku คุณสามารถตรวจสอบอีกครั้งวิดีโอนี้ได้ฟรี
onmyway133

31
การสนทนาแบบกอดกับการต่อต้านเริ่มต้นที่ประมาณ 13:15 จุดในวิดีโอ
Carl Smith

1
@ onmyway133 นี้เป็นวิดีโอที่สมบูรณ์แบบ แต่น่าเสียดายที่ไม่มีตัวอย่างว่า Ray ใช้มันอย่างไร
Matrosov Alexander

@ MatrosovAlexander ฉันคิดว่าตัวอย่างที่ใช้งานได้จริง ๆ ก็คือความสูงของเซลล์แบบไดนามิกด้วย Autolayout fantageek.com/1468/…
onmyway133

1
เขาแสดงวิธีใช้ความต้านทานการบีบอัดเวลา 18:05
Brent Faust

187

ป้อนคำอธิบายรูปภาพที่นี่

แหล่งที่มา: @mokagio

ขนาดเนื้อหาที่แท้จริง - อธิบายด้วยตนเองได้ดี แต่การดูด้วยเนื้อหาที่แปรปรวนนั้นทราบว่าเนื้อหามีขนาดใหญ่เพียงใดและอธิบายขนาดของเนื้อหาผ่านพร็อพเพอร์ตี้นี้ ตัวอย่างที่ชัดเจนของมุมมองที่มีขนาดเนื้อหาภายในคือ UIImageViews, UILabels, UIButtons

ลำดับความสำคัญของเนื้อหา Hugging - ลำดับความสำคัญนี้ที่สูงกว่าคือยิ่งมีมุมมองต่อต้านการขยายใหญ่กว่าขนาดเนื้อหาที่แท้จริง

ลำดับความสำคัญของการบีบอัดเนื้อหา - ลำดับความสำคัญนี้สูงกว่ายิ่งมีมุมมองต่อต้านการย่อขนาดเล็กกว่าขนาดเนื้อหาที่แท้จริง

ตรวจสอบที่นี่เพื่อดูคำอธิบายเพิ่มเติม: Magic LAYOUT AUTO: ลำดับความสำคัญของขนาดเนื้อหา


ภาพประกอบดี แต่พูดให้เข้าใจผิด ผู้ชายที่ดีที่สุดควรพูดว่า "ฉันจะไม่ยอม (ให้ฉัน) เติบโต" มุมมองเด็กกำหนดด้วยตนเองว่ามันไม่ต้องการที่จะเติบโตผ่านพฤติกรรมการกอดเนื้อหา ไม่มีแรงจากภายนอก (เช่นมือที่แสดง) ซึ่งหยุดยั้งการเติบโต นั่นคือความแตกต่างใหญ่
มานูเอล

6
ฉันลงคะแนนนี้เพราะฉันรักภาพประกอบ
James Bucanek

3
นี่คือเหตุผลที่ฉันชอบ Stack Overflow …คำอธิบายของ Snowcrash บวกกับภาพประกอบนี้โดย mokagio = คำอธิบายที่ดีที่สุดของคุณสมบัติเหล่านี้ได้ทุกที่ (รวมถึงเอกสารของ Apple เอง)
Kal

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
ไม่ควรเป็น: ให้ verticalCompression = view.heightAnchor.constraint (GreaterThanOrEqualToConstant: view.intrinsicContentSize.height)
mc_plectrum

1
ใช่ฉันทำข้อผิดพลาดการคัดลอก / วาง ฉันแก้ไขมันแล้ว ขอบคุณที่ทำให้ฉันรู้.
rob mayoff

15

การกอดเนื้อหาและการจัดลำดับความต้านทานการบีบอัดเนื้อหาจะทำงานกับองค์ประกอบที่สามารถคำนวณขนาดได้โดยขึ้นอยู่กับเนื้อหาที่กำลังเข้ามา

จากเอกสารของ Apple :

ป้อนคำอธิบายรูปภาพที่นี่


plus1 สำหรับรูปภาพ (Y)
Noor Ali Butt

ฉันสับสน สำหรับ textView ที่ไม่ได้เปิดใช้งานการเลื่อน นั่นหมายความว่าต่อผู้ใช้ที่พิมพ์ขนาดที่แท้จริงจะเปลี่ยน?
ฮันนี่

@ เงินฉันคิดว่าการตั้งค่าข้อ จำกัด ที่ถูกต้องและเลื่อนปิดการใช้งานมุมมองข้อความควรจะสามารถบอกความสูงที่แท้จริง
dev gr

ไม่ได้ตอบคำถามของฉัน คุณหมายถึงถ้าฉันพิมพ์เยอะมากเกินขนาดปัจจุบันของ textView .... textView จะขยายโดยอัตโนมัติและเปลี่ยนขนาดที่แท้จริง?
ฮันนี่

ลองด้วยตัวคุณเอง กำหนด textview ให้มีความกว้างคงที่และปิดการใช้งานการเลื่อนและตรวจสอบพฤติกรรมที่ต้องการ อ้างถึงstackoverflow.com/a/21287306/1526629สำหรับคำตอบเพิ่มเติม
dev gr

11

Content hugging priorityเป็นเหมือนวงยางที่วางอยู่รอบ ๆ มุมมอง ยิ่งมีค่าความสำคัญสูงขึ้นเท่าไหร่ยางรัดก็จะยิ่งแข็งมากขึ้นเท่านั้น ค่าลำดับความสำคัญสามารถจินตนาการได้เช่นเดียวกับ "ความแข็งแรง" ของยางรัด

และContent Compression Resistanceนั่นคือมุมมอง "ต่อต้าน" มีขนาดเล็กลง มุมมองที่มีค่าลำดับความต้านทานสูงกว่าคือมุมมองที่จะต้านทานการบีบอัด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.