ฉันจะใช้ Autolayout เพื่อกำหนดข้อ จำกัด ใน UIScrollview ของฉันได้อย่างไร


176

ฉันใช้เวลาสองวันในการลองวิธีแก้ปัญหาต่าง ๆ สำหรับวิธีผสมและ Pure Autolayoutเพื่อให้ได้สิ่งที่เป็นการตั้งค่า scrollview เล็กน้อยก่อนการ autolayout และตอนนี้เป็นทางการ - ฉันต้องโง่เกินไป ฉันกำลังตั้งค่านี้ส่วนใหญ่ใน Storyboard (ก็เป็นแบบที่มันเป็น)

ดังนั้นนี่คือข้ออ้างของฉันเพื่อขอความช่วยเหลือ

Viewtree:

UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton

ปุ่มควรเลื่อนในแนวนอน (ซ้ายไปขวาและกลับกัน) ใครช่วยกรุณาแจ้งให้เราทราบวิธีการตั้งข้อ จำกัด เพื่อให้บรรลุนี้โดยใช้ Autolayout บริสุทธิ์ ???

-

ฉันได้ลองใช้วิธีผสมเช่น:

UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton

... และการตั้งค่าข้อ จำกัด ความกว้างและความสูงคงที่สำหรับcontentviewและการtranslatesAutoresizingMaskIntoConstraintsตั้งค่าตาม TechNote ของ Apple ปุ่มและ scrollview ถูกตั้งค่าโดยใช้ข้อ จำกัด สิ่งนี้ทำให้ scrollview scrolling (ใช่) แต่อนิจจามันเลื่อนไปไกลเกินไป! เท่าที่ฉันสามารถบอกได้ความกว้างของการเลื่อนจะเพิ่มขึ้นเป็นสองเท่าจากสิ่งที่ฉันตั้งค่า contentview ที่ ??? !!! ???

ฉันลองใช้วิธี autolayout ที่บริสุทธิ์เช่นกันทั้งที่มีcontentviewและไม่มี ทุกมุมมองที่ยกเว้นtranslatesAutoresizingMaskIntoConstraints=NO self.viewปุ่มเหล่านี้มีข้อ จำกัด ด้านความกว้าง / ความสูงคงที่และถูกตรึงไว้ที่ขอบทั้งสี่ของ scrollview ไม่มีอะไรเลื่อน

ดังนั้นฉันงงงันโดยสิ้นเชิงว่าทำไมฉันไม่สามารถทำงานได้อย่างถูกต้อง ความช่วยเหลือใด ๆ ที่นิยมมากและหากคุณต้องการข้อมูลอื่น ๆ โปรดถาม!

อัปเดตภาพหน้าจอพร้อมโซลูชัน - ข้อ จำกัด buttonZ:

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

EDIT @ Jamie Forrest ดังนั้นการแก้ไขจึงกลายเป็นข้อ จำกัด การลากที่ไม่ถูกต้องในปุ่มสุดท้าย แทนที่จะเป็น 6441 ค่าที่ฉันตั้งไว้เป็นค่าลบ -6441 สิ่งที่ยุ่งยากคือเมื่อตั้งค่าในกระดานเรื่องราวมีสองตัวเลือกในแถบเครื่องมือ Pin:

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

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

แก้ไขอีกครั้ง ตอนนี้เป็นเรื่องตลก ... การเปลี่ยนค่าการต่อท้ายจาก -6441 (ไม่มีการเลื่อน) เป็นการเลื่อนที่เปิดใช้งาน 6441 แต่เพื่อนเก่าของฉัน "เนื้อหาที่มากเกินไป" กลับมานำไปสู่ขนาดเนื้อหาใหญ่เป็นสองเท่าของสิ่งที่ควรจะเป็น! วิธีแก้ปัญหาในการเลื่อนเนื้อหาที่ถูกต้องคือการตั้งค่าข้อ จำกัด ต่อท้ายเป็น ZERO! สิ่งนี้ไม่ชัดเจนเมื่อทำงานในสตอรีบอร์ด แต่เมื่อดูที่รหัส @Infinity James มันเป็นสิ่งที่ควรเป็น


คุณคำนวณ / กำหนดขนาดเนื้อหาสำหรับมุมมองเลื่อนของคุณที่ไหน อ้างถึงความพยายามครั้งแรกของคุณโดยใช้ contentView และคุณบอกว่ามันเลื่อนไปไกลเกินไป
ทิม

2
เท่าที่ฉันรู้คุณไม่สามารถตั้งค่าcontentSizeการUIScrollViewใช้เลย์เอาต์อัตโนมัติเท่านั้น และมันคือสิ่งcontentSizeที่กำหนดว่าคุณสามารถเลื่อนได้มากแค่ไหน ดังนั้นคุณจะต้องตั้งค่านี้ด้วยตนเองที่ไหนสักแห่งในที่สุด สำหรับส่วนที่เหลือคุณสามารถใช้ข้อ จำกัด โครงร่างเพื่อตั้งค่ามุมมองเฟรมสัมพันธ์กัน
Guillaume

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

พิมพ์เนื้อหาของคุณขนาดขณะใช้งานดูว่ามันตรงกับค่าที่คุณมีการป้อนข้อมูล contentSize กำหนดจำนวนการเลื่อนที่เกิดขึ้นดังนั้นปัญหาที่คุณพยายามครั้งแรกคือการใช้ contentSize
ทิม

@ Guillaume ดังนั้นวิธี "autolayout อย่างแท้จริง" จึงไม่บริสุทธิ์อย่างนั้นเหรอ? แต่ฉันจะตั้งค่าขนาดเนื้อหาด้วยตนเองได้อย่างไร ดังที่ฉันได้กล่าวไปแล้วฉันกำลังตั้งค่าความสูง / ความกว้างของมุมมองเนื้อหาที่ค่าคงที่ แต่มันเลื่อนไปไกลเกินไป (2x)
user1459524

คำตอบ:


68

เป็นการยากที่จะเห็นค่าที่แน่นอนและการตั้งค่าข้อ จำกัด ของคุณเมื่อคุณวางมันไว้ที่นี่ดังนั้นฉันจึงไม่แน่ใจจากการดูภาพหน้าจอที่คุณทำผิดไป

แทนที่จะอธิบายว่ามีอะไรผิดปกติในการตั้งค่าของคุณฉันได้สร้างโครงการตัวอย่างพื้นฐานที่มีลำดับชั้นการดูและการตั้งค่าข้อ จำกัด ที่คล้ายคลึงกับที่คุณอธิบายไว้ เลื่อนแนวนอนทำงานตามที่คาดไว้ในโครงการตัวอย่างที่ใช้ "เพียว autolayout" วิธีการที่แอปเปิ้ลอธิบายในหมายเหตุทางเทคนิค

ฉันยังมีปัญหามาก UIScrollViewแต่เดิมได้รับเค้าโครงอัตโนมัติเพื่อให้ทำงานร่วมกับ กุญแจสำคัญในการทำให้มันใช้งานได้คือการทำให้แน่ใจว่ารายการทั้งหมดในมุมมองการเลื่อนนำมารวมกันมีข้อ จำกัด ที่ในที่สุดเชื่อมโยงไปยังทุกด้านของมุมมองเลื่อนและที่นำไปสู่ระบบ AutoLayout สามารถกำหนดขนาดเนื้อหาสำหรับ มุมมองเลื่อนที่จะใหญ่กว่ากรอบ ดูเหมือนว่าคุณกำลังพยายามทำสิ่งนั้นในรหัสของคุณ แต่บางทีคุณอาจมีข้อ จำกัด บางอย่างที่ทำให้เนื้อหามีขนาดเล็กเกินไป

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

ฉันพบว่าบท ebook นี้มีประโยชน์มากในการทำให้ฉันเข้าใจว่าการทำงานทั้งหมดนี้เป็นอย่างไร หวังว่าทั้งหมดนี้จะช่วยให้


2
ขอบคุณสำหรับโครงการตัวอย่าง! มันใช้งานได้และในขณะที่มองผ่านฉันไม่สามารถพบความแตกต่างใด ๆ กับโครงการของฉันในตอนแรก! ฉันคัดลอกมุมมองไปยังโครงการของฉันสงสัยว่าการตั้งค่าอื่น ๆ กว่าข้อ จำกัด แต่มันก็ยังคงทำงาน สิ่งนี้ทำให้ฉันสังเกตเห็นว่าข้อ จำกัด ต่อท้ายสำหรับปุ่มสุดท้ายในโครงการของฉันมีค่าเป็นลบ - อยู่ข้างหน้าในขณะที่คุณมีค่าเป็นบวก! การเปลี่ยน - เป็นค่าบวกเปิดใช้งานการเลื่อน! เมื่อฉันเรียกใช้แถบเครื่องมือ Pin มีสองตัวเลือก: ใช้ค่า Canvas ปัจจุบันซึ่งเป็นค่าลบและมุมมองเลื่อน (ใช้ค่าปัจจุบัน) ซึ่งเป็นค่าบวก ... ?!
user1459524

อ่าใช่ ค่าลบจะทำให้ขนาดเนื้อหาของมุมมองเลื่อนมีขนาดเล็กลงเพื่อให้ตรงกับความจริงที่ว่าส่วนท้ายของขอบควรสิ้นสุดก่อนที่ปุ่มจะสิ้นสุด ดีใจที่โครงการตัวอย่างช่วย!
เจมี่ฟอเรสต์

มันทำได้เยอะมาก ลองดูคำตอบล่าสุดของฉัน ค่าที่ตามมาควรเป็น 0 (ศูนย์) ที่จริงแล้วดูเหมือนว่า
user1459524

6
นั่นคือสิ่งที่น่าเศร้าที่เราต้องแชร์ภาพหน้าจอแทนรหัส นั่นเป็นเพียงเพราะแอปเปิ้ลสนับสนุนให้นักพัฒนาใช้ผู้สร้างแทนที่จะให้ API ที่ดีกว่า
VladimírSlavík

4
ใช้งานง่ายโดยสิ้นเชิง นักพัฒนาต้องเสียเวลาและชั่วโมงเพื่อคิดว่าเกิดอะไรขึ้นในใจของผู้สร้าง XCode
Josh

49

LOL ยินดีต้อนรับสู่สโมสรที่โง่เขลา ฉันเป็นหนึ่งในผู้ก่อตั้ง : D

สำหรับการเลื่อนแนวตั้ง : วิธีเดียวที่ฉันจะทำให้มันใช้งานได้ (iOS 8, Xcode 6 และ autolayout บริสุทธิ์) คือการเพิ่มข้อ จำกัด ต่อไปนี้ใน Scroll View ของฉัน (ทั้งหมดที่เกี่ยวข้องกับผู้ดูแล):

  • ความกว้างเท่ากัน
  • เท่ากับความสูง
  • การจัดศูนย์ Y
  • การจัดศูนย์ X

โครงสร้างของฉัน:

  UIView
   - ScrollView
    - Subview
    - Subview
    - Subview
    - Subview
    - ...

นี่คือผลลัพธ์สุดท้าย:

การสาธิต

นี่คือการตั้งค่า:

ติดตั้ง เต็มจอ

และนี่คือโครงการ

หวังว่านี่จะช่วยชีวิตใครบางคนจากการไปนอนในเวลาตี 5 : D


ขอบคุณมากสำหรับความช่วยเหลือ! คุณได้รับมุมมองย่อยของประเภท "มุมมองย่อย" ได้อย่างไร ฉันกำลังดูโครงการของคุณใน Xcode 6.2 และมันเรียกว่ามุมมองย่อย "Subview" ที่มีข้อ จำกัด เพียงอย่างเดียวนั่นคือ 63px สูง
Andrew K

1
ทักทาย! "Subview" นั้นแท้จริงแล้วเป็น UIVIew นั่นเป็นเพียงชื่อ ... คุณสามารถพิมพ์อะไรก็ได้ที่นั่น ดูภาพนี้: cl.ly/image/291f1K2N0V3pในหัวข้อข้อ จำกัด การชมย่อยมีมากกว่าข้อ จำกัด สูง ตรวจสอบรายการข้อ จำกัด ทั้งหมดสำหรับมุมมองเหล่านี้ที่นี่: cl.ly/image/3l061i123j2i
backslash-f

1
ฉันยังคงเลื่อนการทำงานไม่ได้ - ฉันสังเกตเห็นว่าการดูย่อยของคุณเป็น "greyed out" ในโครงการของคุณ หลังจากทำวิจัยแล้วดูเหมือนว่านี่เป็นเพราะคุณกำลังใช้ 'ขนาดเรียน' สิ่งนี้มีผลต่อการเลื่อนอย่างไร? มีวิธีการเลื่อนการทำงานโดยไม่ใช้หรือไม่
แอนดรู K

นอกจากนี้คุณทำให้การกำกับดูแลของคุณนานกว่าความยาวเริ่มต้นได้อย่างไร? ฉันกำลังพยายามเพิ่มปุ่มที่จะปรากฏ "ครึ่งหน้าล่าง" (หรือปิดหน้าจอ) แต่เห็นได้ชัดว่าฉันไม่สามารถเพิ่มพวกเขาไปยัง superview ถ้าฉันไม่สามารถลากและวางพวกเขาลงบน superview เพราะมันไม่ใหญ่พอ
แอนดรู K

1
หลังจากวันที่ยาวนานในการค้นหาและพยายามทำรูปแบบที่โง่เขลาฉันพบคำตอบนี้และใช้งานได้ในตอนแรกลอง .. ขอบคุณผู้ชาย .. คุณบันทึกวันของฉัน .. ฉันหวังว่าฉันจะให้คะแนนพันคะแนนสำหรับคำตอบนี้ .. : )
Bobby Stenly

32

ตัวอย่างที่เรียบง่ายบรรจุในตัวเอง

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

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

คำถามเดิมถามเกี่ยวกับปุ่มเลื่อน ที่นี่ฉันเพิ่งใช้UIViews แต่พวกเขาสามารถแสดงสิ่งที่คุณต้องการ ฉันยังเลือกการเลื่อนในแนวนอนเนื่องจากภาพหน้าจอของกระดานเรื่องราวมีขนาดเล็กลงสำหรับรูปแบบนี้ หลักการก็เหมือนกันสำหรับการเลื่อนแนวตั้ง

แนวคิดหลัก

  • UIScrollViewควรใช้เฉพาะหนึ่ง subview นี่คือ 'UIView' ที่ทำหน้าที่เป็นมุมมองเนื้อหาเพื่อเก็บทุกสิ่งที่คุณต้องการเลื่อน
  • ทำให้มุมมองเนื้อหาและมุมมองการเลื่อนของผู้ปกครองมีความสูงเท่ากันสำหรับการเลื่อนแนวนอน (ความกว้างเท่ากับการเลื่อนแนวตั้ง)
  • ตรวจสอบให้แน่ใจว่าเนื้อหาที่เลื่อนได้ทั้งหมดมีความกว้างที่กำหนดและถูกตรึงไว้กับทุกด้าน

เริ่มโครงการใหม่

มันเป็นเพียงแอปพลิเคชันมุมมองเดียว

สตอรี่บอร์ด

ในตัวอย่างนี้เราจะทำให้มุมมองเลื่อนแนวนอน เลือก View Controller จากนั้นเลือก Freeform ใน Size Inspector ทำให้ความกว้างและความสูง1,000 300สิ่งนี้ทำให้เรามีพื้นที่บนกระดานเรื่องราวเพื่อเพิ่มเนื้อหาที่จะเลื่อน

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

เพิ่มมุมมองเลื่อน

เพิ่มUIScrollViewและปักหมุดทั้งสี่ด้านเข้ากับมุมมองรูทของคอนโทรลเลอร์มุมมอง

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

เพิ่มมุมมองเนื้อหา

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

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

เท่ากับความสูง

ตอนนี้ในโครงร่างเอกสารให้Commandคลิกมุมมองทั้งเนื้อหาและมุมมองเลื่อนของมุมมองของผู้ปกครองในการสั่งซื้อเพื่อเลือกพวกเขาทั้งสอง จากนั้นตั้งค่าความสูงให้เท่ากัน ( Controlลากจาก Content View ไปที่ Scroll View) นี่คือกุญแจ เนื่องจากเรากำลังเลื่อนในแนวนอนมุมมองเนื้อหาของมุมมองเลื่อนจะไม่ทราบว่าควรจะสูงเท่าไรเว้นแต่เราจะตั้งค่าด้วยวิธีนี้

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

บันทึก:

  • หากเราทำการเลื่อนเนื้อหาในแนวตั้งเราจะตั้งค่าความกว้างของมุมมองเนื้อหาให้เท่ากับความกว้างของมุมมองพาเรนต์

เพิ่มเนื้อหา

เพิ่มสามUIViews และให้ข้อ จำกัด ทั้งหมดกับพวกเขา ฉันใช้ระยะขอบ 8 จุดสำหรับทุกสิ่ง

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

ข้อ จำกัด :

  • มุมมองสีเขียว: ปักหมุดด้านบนซ้ายและขอบด้านล่าง ทำให้ความกว้าง 400
  • มุมมองสีแดง: ตรึงขอบด้านบนซ้ายและขอบด้านล่าง ทำให้ความกว้าง 300
  • มุมมองสีม่วง: ตรึงขอบทั้งสี่ของขอบ ทำให้ความกว้างไม่ว่าพื้นที่ที่เหลือจะเป็นเท่าใด (268 ในกรณีนี้)

การตั้งค่าข้อ จำกัด ด้านความกว้างเป็นกุญแจสำคัญเช่นกันเพื่อให้มุมมองเลื่อนรู้ได้ว่ามุมมองเนื้อหากว้างแค่ไหน

เสร็จ

นั่นคือทั้งหมดที่ คุณสามารถเรียกใช้โครงการของคุณตอนนี้ มันควรทำตัวเหมือนภาพเลื่อนที่ด้านบนของคำตอบนี้

สำหรับการเลื่อนในแนวตั้งเพียงสลับทิศทางความกว้างและความสูงทั้งหมดในตัวอย่างนี้ (ทดสอบและใช้งาน)

การศึกษาต่อ


9

contentSize ถูกตั้งค่าโดยนัยโดยใช้ข้อ จำกัด ภายในของ UIScrollView

ตัวอย่างเช่นคุณมี UIScrollView อยู่ภายใน UIView ซึ่งจะมีลักษณะเช่นนี้ (เพราะฉันแน่ใจว่าคุณทราบแล้ว):

    UIView *containerView               = [[UIView alloc] init];
    UIScrollView *scrollView            = [[UIScrollView alloc] init];
    [containerView addSubview:scrollView];
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    scrollView.translatesAutoresizingMaskIntoConstraints    = NO;
    NSDictionary *viewsDictionary       = NSDictionaryOfVariableBindings(containerView, scrollView);

    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil
                                                                            views:viewsDictionary]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil

ที่จะตั้งค่า scrollView ให้เติมขนาดของ containerView (ดังนั้น containerView จะต้องมีขนาดที่แน่นอน)

จากนั้นคุณสามารถปรับขนาดเนื้อหาของ UIScrollView โดยการตั้งค่าให้มีขนาดใหญ่พอที่จะกดปุ่มดังนี้:

    UIButton *buttonA                   = [[UIButton alloc] init];
    UIButton *buttonB                   = [[UIButton alloc] init];
    UIButton *buttonC                   = [[UIButton alloc] init];
    [scrollView addSubview:buttonA];
    [scrollView addSubview:buttonB];
    [scrollView addSubview:buttonC];
    buttonA.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonB.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonC.translatesAutoresizingMaskIntoConstraints       = NO;

    viewsDictionary                     = NSDictionaryOfVariableBindings(scrollView, buttonA, buttonB, buttonC);

    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonA]-|"
                                                                       options:kNilOptions
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[buttonA]-[buttonB]-[buttonC]-|"
                                                                       options:NSLayoutFormatAlignAllBaseline
                                                                       metrics:nil
                                                                         views:viewsDictionary]];

ดังนั้นฉันตั้งข้อ จำกัด ระหว่าง scrollView และปุ่มไม่ใช่ containerView และปุ่ม? ฉันคิดว่านั่นเป็นเรื่องเกี่ยวกับความแตกต่างเพียงอย่างเดียวที่ฉันกำลังทำในระหว่างโค้ดของคุณและสิ่งที่ฉันกำลังทำผ่านกระดานเรื่องราวตอนนี้
user1459524

ฉันเพิ่งรู้หลังจากอ่านครั้งที่สองว่าคุณกำลังตั้งค่ามุมมอง CONTAINER และไม่ใช่มุมมอง ตามรหัสของคุณฉันได้สร้างทุกอย่างขึ้นมาใหม่ในสตอรี่บอร์ดและมันไม่ได้เลื่อน ฉันจะแก้ไขคำถามของฉันด้วยภาพหน้าจอบางอย่าง
user1459524

1
ดังนั้นความพยายามของฉันในการสร้างรหัสในสตอรีบอร์ดนั้นไม่ถูกต้อง 100% ค่าการติดตามสำหรับปุ่มสุดท้ายควรเป็นศูนย์อย่างแน่นอนการทำมิรเรอร์ H: | - [buttonA] - [buttonB] - [buttonC] - | ซึ่งไม่ชัดเจนมากเมื่อทำงานในกระดานเรื่องราว (หรืออย่างน้อยก็ไม่ใช่สำหรับฉัน) แต่ตอนนี้หลังจากข้อเท็จจริงดูเหมือนเล็กน้อย ฉันรักการเล่นอัตโนมัติ แต่สิ่งเล็ก ๆ น้อย ๆ เหล่านั้นทำให้คุณได้รับ ...
user1459524

สิ่งที่ @ user1459524 กล่าวถึงเป็นปัญหาสำหรับฉัน มุมมองด้านล่างของฉันคือปุ่มและข้อ จำกัด ด้านล่างคือ -32 โดย IB ฉันตั้งค่าเป็น 0 และได้รับการปรับปรุงใน IB ให้เป็น Bottom Space เป็น: superview มันจะทำงานได้เหมือนกันตราบใดที่คุณยังอยู่ในด้านบวก ดูเหมือนว่าอาจเป็นข้อผิดพลาดกับ IB หวังว่าจะช่วยคนอื่น ฉันลบมุมมองทั้งหมดและเดินสายอีกครั้งซึ่งช่วยเมื่อพยายามจัดวางสิ่งเหล่านี้ที่ฉันพบและมักใช้เวลาไม่นาน
Michael

8

มีคำถามมากมายเกี่ยวกับการใช้ AutoLayout กับ UIScrollView จุดสำคัญที่เราเพิกเฉยคือมุมมองภายในของ UIScrollView สร้างข้อ จำกัด ต่อมุมมองเนื้อหาแต่ไม่ใช่ UIScrollView อ้างอิงถึงหมายเหตุทางเทคนิค TN2154คุณสามารถค้นหา:

คลาส UIScrollView เลื่อนเนื้อหาโดยเปลี่ยนที่มาของขอบเขต ในการทำให้การทำงานกับเลย์เอาต์อัตโนมัติตอนนี้ขอบด้านบนซ้ายด้านล่างและด้านขวาภายในมุมมองเลื่อนนั้นหมายถึงขอบของมุมมองเนื้อหา

รูปต่อไปนี้จะแสดงให้เห็นว่า: ป้อนคำอธิบายรูปภาพที่นี่

คุณสามารถค้นหาพื้นที่ต่อท้ายได้ 500 คะแนนหากมีข้อ จำกัด ใน UIScrollView มุมมองจะหายไปและควรอัปเดตเฟรม อย่างไรก็ตามไม่มีคำเตือนและไม่มีข้อผิดพลาด เพราะข้อ จำกัด ทั้งหมดนั้นขัดกับมุมมองเนื้อหา

UIScrollView จะคำนวณขนาดของมุมมองเนื้อหาตามข้อ จำกัด ของมุมมองภายใน (ตัวอย่างเช่นขนาดเนื้อหา: ความกว้าง = 100 (พื้นที่นำหน้า) + 200 (ความกว้างของมุมมอง) + 500 (พื้นที่ต่อท้าย), ความสูง = 131 (ระยะห่างสูงสุด) + 200 (สูง) + 269 (ระยะห่างด้านล่าง)

วิธีเพิ่มข้อ จำกัด สำหรับมุมมองใน UIScrollView:

  1. การถ่ายภาพตำแหน่งของมุมมองในมุมมองเนื้อหา
  2. เพิ่มระยะห่างด้านบนขวาล่างซ้ายไปที่ขอบของมุมมองเนื้อหารวมถึงความกว้างและความสูงของมุมมองเหล่านี้

และทุกอย่างเสร็จสิ้น

วิธีที่ง่ายในการจัดการกับ AutoLayout ด้วย scrollview คือการเพิ่มมุมมองคอนเทนเนอร์ที่มีการดูทั้งหมดในมุมมองเลื่อน

สรุป: จุดสำคัญที่จะเข้าใจ AutoLayout ด้วย UIScrollView คือมุมมองภายในทำให้ข้อ จำกัด กับมุมมองเนื้อหา แต่ไม่ใช่ UIScrollView

รหัสตัวอย่างที่แนบมา


5

วิธีแก้ปัญหาต่อไปนี้ทำงานสำหรับฉันสำหรับscrollView ด้วยการชำระอัตโนมัติและไม่มี contentSize :

  1. ลาก n เลื่อน scrollView ไปที่ viewController และใช้ข้อ จำกัด อะไรก็ตามเพื่อครอบคลุมพื้นที่ที่คุณต้องการ
  2. ลาก n วางUIViewภายใน scrollView และทำให้ครอบคลุมพื้นที่ทั้งหมดของ scrollView และใช้ข้อ จำกัด ด้านบนซ้ายซ้ายขวาช่องว่างด้านล่างจาก scrollView
  3. ตั้งค่าความสูง (และความกว้างหากจำเป็นต้องเลื่อนแนวนอน) ของมุมมองด้านในตามความต้องการของการเลื่อน ส่วนนี้สามารถทำได้จากรหัสถ้าจำเป็น
  4. สำคัญมาก หลังจากที่คุณตั้งค่าความสูงเป็นค่าขนาดใหญ่ในจุด (3) ให้กลับไปที่จุด (2) และตั้งค่าด้านบนซ้ายขวาขวาล่างเป็นศูนย์เนื่องจาก Xcode อาจเปลี่ยนให้คุณเมื่อคุณบังคับ เปลี่ยนความสูงเป็น (3)

และคุณทำเสร็จแล้ว ตอนนี้คุณสามารถเพิ่มจำนวนการควบคุมใด ๆ ในมุมมองนี้และใช้ข้อ จำกัด ที่เกี่ยวข้องกับแต่ละอื่น ๆ (ซึ่งดูเหมือนจะไม่ทำงานหากไม่มีมุมมองนี้) หากคุณไม่ต้องการใช้มุมมองนี้คุณจะต้องใช้ข้อ จำกัด สำหรับการควบคุมแต่ละรายการที่เกี่ยวข้องกับ scrollView (ไม่เกี่ยวข้องกัน)


เคล็ดลับที่ท่วมท้น ..............

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

โปรดทราบว่าตอนนี้ความกว้างของมุมมองเนื้อหานั้นใหญ่กว่าความกว้างของมุมมองการเลื่อนพาเรนต์ 225 ไม่เป็นไร: ที่จริงแล้วคุณต้องทำอย่างนั้น สังเกตได้ว่า

... คุณไม่ได้ตั้งค่าความกว้างต่อท้ายเป็นค่าลบ 225 ...

คุณจะคิดว่าคุณต้อง "จับคู่" ความกว้างตามปกติ แต่ถ้าคุณทำอย่างนั้นมันจะไม่ทำงานเลย

คุณต้องตั้งค่าตัวเลขนำหน้าและต่อท้ายเป็นศูนย์ไม่เป็นลบ (แม้ว่าความกว้างจะเป็น "ใหญ่กว่า")

ที่น่าสนใจคุณสามารถกำหนดจำนวนนำหน้า / ต่อท้ายเป็นค่าบวกใด ๆ(ลองพูดว่า "50") และจะให้ระยะขอบของการตีกลับ (มักจะดูดีมาก: ลองดู) ค่าลบใด ๆ ที่ปลายทั้งสองข้างจะ "แตกอย่างเงียบ ๆ "

โปรดทราบว่าโดยปกติแล้ว Xcode (ณ 7.3.1 อยู่ดี)

จะ 'ช่วย' ตั้งค่าเหล่านั้นให้คุณเป็นจำนวนลบ!

เพราะมันจะพยายามนับพวกเขาให้คุณโดยอัตโนมัติ ถ้าเป็นเช่นนั้นมันจะหยุดพักอย่างเงียบ ๆ ตั้งค่าทั้งสี่ให้เป็นศูนย์ในอินสแตนซ์แรก และตั้งค่าความกว้างของมุมมองเนื้อหาที่กว้างกว่า "1000" ในตัวอย่าง


แก้ไข: ฉันลงเอยด้วยการใช้ UITableView แทน UIScrollView สำหรับความต้องการส่วนใหญ่ของฉัน ในฐานะที่เป็น tableView ดูเหมือนว่าฉันมีความยืดหยุ่นและแบบไดนามิกมากขึ้น


นี่คือคำตอบที่ดีที่สุดที่นี่ ขอบคุณ!
Fattie

4

contentSizeผมถือว่าคุณกำลังวิ่งเข้าไปในปัญหาเกี่ยวกับ ลองอ่านโพสต์บล็อกนี้เกี่ยวกับวิธีการจัดการcontentSizeเมื่อใช้วิธีการ "วางตัวแบบอัตโนมัติ" ส่วนสำคัญของมันคือข้อ จำกัด ของคุณกำหนดขนาดเนื้อหาโดยปริยาย คุณไม่ควรตั้งค่าอย่างชัดเจนเมื่อใช้ AutoLayout ฉันได้แนบโปรเจ็กต์ตัวอย่างในตอนท้ายของโพสต์บล็อกเพื่อสาธิตวิธีการทำงาน


3

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

นี่คือตัวอย่างง่ายๆ สร้างกระดานเรื่องราวด้วยมุมมองเดียวที่มีมุมมองเลื่อน กำหนดข้อ จำกัด มุมมองการเลื่อนเพื่อให้พอดีกับขนาดของมุมมองที่คุณใส่

ภายในมุมมองเลื่อนนั้นเพิ่มมุมมองเดียว กำหนดขนาดของมุมมองนั้นอย่างชัดเจนโดยใช้ข้อ จำกัด (และตรวจสอบให้แน่ใจว่าขนาดใหญ่กว่ามุมมองเลื่อน)

ตอนนี้เพิ่มข้อ จำกัด เพิ่มเติมอีกสี่ข้อในมุมมองด้านในที่ล็อคขอบสี่ด้านของมุมมองด้านในลงในมุมมองเลื่อนหลัก ข้อ จำกัด ทั้งสี่นี้จะทำให้ขนาดเนื้อหาขยายเพื่อรองรับมุมมองภายใน

หากคุณมีหลายมุมมองที่คุณต้องการเพิ่มลงในมุมมองเลื่อนตัวอย่างเช่นวางในแนวนอนคุณจะล็อคด้านซ้ายของมุมมองย่อยแรกทางด้านซ้ายของมุมมองเลื่อนล็อคมุมมองซึ่งกันและกันในแนวนอนและด้านขวา ด้านข้างของมุมมองย่อยสุดท้ายไปทางด้านขวาของมุมมองเลื่อน ข้อ จำกัด เหล่านั้นจะบังคับให้ขนาดเนื้อหาของมุมมองเลื่อนเพื่อขยายเพื่อรองรับการตอบรับทั้งหมดและข้อ จำกัด


3

หากคำถามของคุณคือ "ฉันจะใส่ UITextFields ไว้ใน UIScrollView แบบเลื่อนในแนวตั้งได้อย่างไรเพื่อให้พวกเขาย้ายออกจากทางของแป้นพิมพ์เมื่อพวกเขามีโฟกัส" คำตอบที่ดีที่สุดคือ:

อย่า

ใช้ UITableViewController กับเซลล์แบบคงที่แทน

คุณจะได้รับพฤติกรรมการเลื่อนออกจากทางนี้ได้ฟรีและเนื้อหาทั้งหมดจะใช้งานได้หากตัวควบคุมมุมมองของคุณแสดงภายใน UINavigationController


3

คุณควรจัดระเบียบเค้าโครงเช่นนี้
ViewControllerViewประกอบด้วยScrollView, ScrollViewประกอบด้วยContainerView, ContainerViewมี 2Labels
ป้อนคำอธิบายรูปภาพที่นี่

จากนั้นทำตาม 3 ขั้นตอนเพื่อให้ScrollViewสามารถเลื่อนได้

  1. การตั้งค่าScrollViewพิน (บน / ขวา / ล่าง / ซ้าย) ถึงViewControllerView
    • การตั้งค่าContainerViewพิน (บน / ขวา / ล่าง / ซ้าย) ถึงScrollView
    • ตั้งค่าHorizontally in Container( ไม่ได้ตั้งค่าVertically in Container)
    • Label1ปักหมุด ( บน / ขวา / ซ้าย) ถึงContainerView
    • Label1ปักหมุด (ขวา / ซ้าย / ล่าง ) ถึงContainerViewและบนไปLabel1

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

นี่คือโครงการตัวอย่าง

หวังว่าความช่วยเหลือนี้


1

วิธี autolayout ที่บริสุทธิ์นั้นทำงานได้อย่างสวยงาม แต่มันก็เป็นความเจ็บปวดที่จะเกิดขึ้นหากคุณย้ายจากที่ไม่ใช่ autolayout ฉันทำไปแล้วสองสามครั้งและฉันมีเคล็ดลับทั่วไปบางประการ:

  • เริ่มต้นเล็ก ๆ : แม้ว่ามันจะหมายถึงการสร้างมุมมองสตอรีบอร์ดของคุณใหม่เริ่มต้นด้วยองค์ประกอบเพียงเล็กน้อยและสร้างมุมมองของคุณอย่างช้าๆตรวจสอบให้แน่ใจว่าการทดสอบการเลื่อนทำงานหลังจากเพิ่มองค์ประกอบบางอย่าง
  • ปิดการแปลช่วยลดภาระให้ทุกอย่าง: นี่เป็นสาเหตุของความขัดแย้งที่เกิดขึ้นกับฉันเสมอ
  • ตั้งค่าข้อ จำกัด UIScrollView ของคุณอย่างถูกต้อง: ตรวจสอบให้แน่ใจว่ามุมมองเลื่อนเชื่อมต่อจากทุกด้านไปยังมุมมองหลักไม่เช่นนั้นจะไม่ขยายเลย

1

หลังจากใช้เวลานานในการจัดการกับปัญหานี้ในที่สุดฉันก็พบวิธีแก้ปัญหา ฉันทำงานกับกระดานเรื่องราวขนาดสากล (600x600) ฉันสร้าง UIView (contentView) ขนาดของ scrollView และสร้างข้อ จำกัด สำหรับ Top, Bottom, Leading และ Trailing to scrollView จากนั้นฉันก็ตัดขนาดของ contentView เป็น 600x600 ด้วยตนเอง กระดานเรื่องราวหยุดพยายามปรับขนาดทุกอย่างและฉันสามารถทำงานได้ แต่มุมมองดูน่ากลัวบนอุปกรณ์จริงหรืออุปกรณ์จำลอง ฉันทำข้อ จำกัด 2 ช่องสำหรับขนาดที่ถูกตัดนี้

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidthConstraint; 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewHeightConstraint;

จากนั้นใน viewDidLoad

CGSize viewSize = self.view.frame.size;
self.contentViewWidthConstraint.constant = viewSize.width;
self.contentViewHeightConstraint.constant = viewSize.height;

ใช้งานได้ดี


1

ฉันใช้เวลาหลายวันพยายามหาวิธีใช้ AutoLayout เพื่อดู Scrollview ในตัวเพื่อจัดให้มี scrollview ในหน้าจอที่มองเห็นซึ่งทำงานได้กับทุกอุปกรณ์ / มิติหน้าจอรวมถึงการหมุนหน้าจอ

ฉันใช้เวลาหลายวันพยายามที่จะทำกับ Autolayout เท่านั้นและเข้าใกล้ แต่ไม่เคยปิดพอ ดังนั้นในที่สุดฉันก็ต้องเพิ่มรหัส 3 บรรทัดต่อหน้าจอเช่นกันใน viewDidLoad

ดูวิธีแก้ปัญหาด้านล่าง:

  1. สร้าง scrollview และเติมวัตถุใด ๆ ที่คุณต้องการ
  2. เปิดเลย์เอาต์อัตโนมัติ
  3. จากนั้นจัดกึ่งกลางของ ScrollView ในแนวตั้งและแนวนอน ตรงกลาง ScrollView
  4. เลือกมุมมองจากนั้น'เพิ่มข้อ จำกัด ที่ขาดหายไป' - สิ่งนี้จะทำสิ่งนั้น
  5. ผลที่ได้คือข้อ จำกัด มากมายถูกสร้างขึ้น มีการสร้างขึ้นใหม่ 2 รายการสำหรับมุมมอง: 'เลื่อนดู Space Horizo ​​nt to View' และ 'เลื่อน Space scrollview เพื่อดู' หรือกลับกัน
  6. ลบ 'Horizo ​​nt space scrollview ไปที่ View' เพื่อให้คุณมีข้อ จำกัด 3 ข้อในมุมมอง 2 สำหรับการป้อน scrollview ในมุมมองและมุมมองหนึ่งเพื่อกำหนดช่องว่างแนวตั้งระหว่าง scrollview และมุมมอง
  7. ตอนนี้เชื่อมโยงข้อ จำกัด Vert กับรหัสของคุณโดยคลิกและ Ctrl ลากไปยังไฟล์ส่วนหัวและสร้าง NSLayoutConstraint IBOutlet (ฉันเรียกว่า mine constraintVertVtoSV)
  8. ตอนนี้ไปที่ไฟล์. m และเพิ่มบรรทัดของรหัสเหล่านี้ลงใน viewDidLoad (เล่นด้วยจำนวนช่องว่างภายในเพื่อรับจุดกึ่งกลางที่ถูกต้อง)

    if (IPAD)

    {self.constraintVertVtoSV.constant = 150.0; }

  9. ตอนนี้ควรทำงานบนอุปกรณ์ทั้งหมดและอยู่กึ่งกลางอย่างถูกต้องและยังคงเลื่อนอย่างถูกต้อง


1

หากชอบฉันคุณเพียงแค่ใช้เนื้อหาแบบสแตติกโดยไม่มีคำแนะนำภายในมุมมองย่อยเช่นคุณสามารถทำสิ่งนี้ได้:

override func viewDidLayoutSubviews() {
    scrollView.contentSize = CGSizeMake(320, 800)
}

1

ปัญหาที่คล้ายกันฉันมีวันนี้กับ iOS 8.4, Xcode 6.4

มีมุมมองที่มีมุมมองเลื่อนที่มี contentView (UIView) ที่มีการชมย่อย

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

แต่เดิมมุมมองเนื้อหาจะปฏิเสธขนาดเป็นความกว้างเต็มของมุมมองเลื่อน ฉันต้องเพิ่มข้อ จำกัด เพิ่มเติมในมุมมองเนื้อหาเพื่อให้ความกว้างตรงกับมุมมองการเลื่อนพาเรนต์หลัก หรือฉันสามารถตั้งข้อ จำกัด contentView.centerX == scrollView.centerX หนึ่งในนั้นนอกเหนือจากการปักหมุดที่ขอบทำให้ขนาดของมุมมองเนื้อหาในทันที

// Either one of these additional constraints are required to get autolayout to correctly layout the contentView. Otherwise contentView size is its minimum required size
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0.0))

การปักขอบของมุมมองเนื้อหาไปยังมุมมองเลื่อนโดยใช้ข้อ จำกัด ทางสายตาของแบบฟอร์ม

let cvConstraints = ["H:|[contentView]|", "V:|[contentView]|"]

ฉันใช้กิจวัตรเพื่อวนซ้ำอาร์เรย์และเพิ่มลงใน scrollView


1

ฉันประสบปัญหาคล้ายกัน ฉันตั้งข้อ จำกัด ทุกข้อและสงสัยอยู่เสมอว่าทำไมมันยังปรับขนาดการดูย่อย วิธีแก้ปัญหาของฉันคือการตั้งคลิปไปที่ YES


1

ในที่รวดเร็วคุณสามารถใช้วิธีการแก้ปัญหาการทำงาน

contraints

ScrollView: นำหน้า, ต่อท้าย, บน, ล่าง = Superview

ContentView: นำหน้า, ต่อท้าย, บน, ล่าง = ScrollView ความสูงคงที่ / สัมพันธ์กับเนื้อหา

คุณสามารถตั้งค่าข้อ จำกัด ความกว้าง (contentView) ให้เท่ากับ scrollView superview แต่เลือก remove remove ในเวลา build เนื่องจากคุณจะเพิ่มข้อ จำกัด ดังกล่าวโดยทางโปรแกรม นี่เป็นเพียงเพื่อให้ IB ไม่ได้บ่นกับคำเตือน

extension UIView {

    func setupContentViewForViewWithScroll(contentView vwContent : UIView) {
        //Set constraint for scrollview content
        let constraint = NSLayoutConstraint(item: vwContent, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.size.width)
        vwContent.addConstraint(constraint)
        self.layoutSubviews()
    }

}

และใน View Controller viewDidLayoutSubviewsฉันแค่เรียกวิธีนี้:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.view.setupContentViewForViewWithScroll(contentView: vwContent)
}

0

ฉันรู้ว่านี่เป็นวิธีแก้ปัญหาของคนธรรมดาและไม่ใช่สิ่งที่ Apple แนะนำใน docu แต่มันใช้งานได้สำหรับฉันสองครั้งด้วยเนื้อหาที่แตกต่างและสามารถตั้งค่าได้อย่างรวดเร็ว: ในตัวควบคุมมุมมองกระดานเรื่องราวแทรก UIView ใน UIView แทรกมุมมองตาราง, ไดนามิก, 0 เซลล์ต้นแบบ, สไตล์ธรรมดาหรือจัดกลุ่ม ในมุมมองตารางจะแทรกมุมมองแบบเลื่อนในเนื้อหาของมุมมองแบบเลื่อนจะแทรก นั่นคือไม่มีการตั้งค่าในตัวควบคุมมุมมองที่กำหนดเอง

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