อัปเดตสำหรับ Swift 5
preferredLayoutAttributesFittingAttributes
เปลี่ยนชื่อเป็นpreferredLayoutAttributesFitting
และใช้การปรับขนาดอัตโนมัติ
อัปเดตสำหรับ Swift 4
systemLayoutSizeFittingSize
เปลี่ยนชื่อเป็น systemLayoutSizeFitting
อัปเดตสำหรับ iOS 9
หลังจากเห็นการแก้ปัญหา GitHub ของฉันภายใต้ iOS 9 ในที่สุดฉันก็มีเวลาที่จะตรวจสอบปัญหาอย่างเต็มที่ ตอนนี้ฉันได้ปรับปรุง repo เพื่อรวมตัวอย่างของการกำหนดค่าต่างๆสำหรับเซลล์ที่ปรับขนาดด้วยตนเอง ข้อสรุปของฉันคือเซลล์ปรับขนาดตัวเองนั้นยอดเยี่ยมในทางทฤษฎี แต่ยุ่งในทางปฏิบัติ คำเตือนเมื่อดำเนินการกับเซลล์การปรับขนาดด้วยตนเอง
TL; DR
ลองดูโครงการ GitHubของฉัน
เซลล์การปรับขนาดด้วยตนเองรองรับเฉพาะผังการไหลเพื่อให้แน่ใจว่าสิ่งที่คุณกำลังใช้อยู่
มีสองสิ่งที่คุณต้องตั้งค่าเพื่อให้เซลล์ปรับขนาดด้วยตนเองทำงานได้
1. ชุดestimatedItemSize
บนUICollectionViewFlowLayout
เค้าโครงเลย์เอาต์จะเป็นแบบไดนามิกในธรรมชาติเมื่อคุณตั้งค่าestimatedItemSize
คุณสมบัติ
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
2. เพิ่มการรองรับการปรับขนาดบนคลาสย่อยของเซลล์
มาใน 2 รสชาติ; Auto-เค้าโครงหรือpreferredLayoutAttributesFittingAttributes
แทนที่กำหนดเอง
สร้างและกำหนดค่าเซลล์ด้วยเค้าโครงอัตโนมัติ
ฉันจะไม่เข้าไปดูรายละเอียดเกี่ยวกับสิ่งนี้เนื่องจากมีโพสต์ SO ที่ยอดเยี่ยมเกี่ยวกับการกำหนดค่าข้อ จำกัด สำหรับเซลล์ เพียงระวังว่าXcode 6 ทำสิ่งต่าง ๆ ด้วย iOS 7 ดังนั้นถ้าคุณรองรับ iOS 7 คุณจะต้องทำสิ่งต่าง ๆ เช่นตรวจสอบให้แน่ใจว่าตั้งค่า autoresizingMask บน contentView ของเซลล์และขอบเขต contentView ถูกตั้งค่าเป็นขอบเขตของเซลล์เมื่อ โหลดเซลล์แล้ว (เช่นawakeFromNib
)
สิ่งที่คุณต้องระวังก็คือเซลล์ของคุณจะต้องมีข้อ จำกัด อย่างจริงจังมากกว่าเซลล์ Table View ตัวอย่างเช่นหากคุณต้องการให้ความกว้างเป็นแบบไดนามิกเซลล์ของคุณจะต้องมีข้อ จำกัด ด้านความสูง ในทำนองเดียวกันหากคุณต้องการให้ความสูงเป็นแบบไดนามิกคุณจะต้อง จำกัด ความกว้างให้กับเซลล์ของคุณ
นำไปใช้preferredLayoutAttributesFittingAttributes
ในเซลล์ที่กำหนดเองของคุณ
เมื่อฟังก์ชั่นนี้เรียกว่ามุมมองของคุณได้รับการกำหนดค่าด้วยเนื้อหาแล้ว (เช่นcellForItem
ถูกเรียก) สมมติว่าข้อ จำกัด ของคุณได้รับการตั้งค่าอย่างเหมาะสมคุณอาจมีการใช้งานเช่นนี้:
//forces the system to do one layout pass
var isHeightCalculated: Bool = false
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
//Exhibit A - We need to cache our calculation to prevent a crash.
if !isHeightCalculated {
setNeedsLayout()
layoutIfNeeded()
let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
var newFrame = layoutAttributes.frame
newFrame.size.width = CGFloat(ceilf(Float(size.width)))
layoutAttributes.frame = newFrame
isHeightCalculated = true
}
return layoutAttributes
}
หมายเหตุบน iOS 9 พฤติกรรมเปลี่ยนไปเล็กน้อยซึ่งอาจทำให้เกิดปัญหากับการใช้งานของคุณหากคุณไม่ระวัง (ดูเพิ่มเติมที่นี่ ) เมื่อคุณใช้งานpreferredLayoutAttributesFittingAttributes
คุณจำเป็นต้องตรวจสอบให้แน่ใจว่าคุณเปลี่ยนเฟรมของคุณลักษณะเลย์เอาต์ของคุณเพียงครั้งเดียว หากคุณไม่ทำเช่นนี้โครงร่างจะเรียกการใช้งานของคุณไปเรื่อย ๆ และจะล้มเหลวในที่สุด ทางออกหนึ่งคือการแคชขนาดที่คำนวณได้ในเซลล์ของคุณและทำให้เป็นโมฆะเมื่อใดก็ตามที่คุณใช้เซลล์นั้นซ้ำหรือเปลี่ยนแปลงเนื้อหาตามที่ฉันได้ทำกับisHeightCalculated
คุณสมบัติ
สัมผัสกับเค้าโครงของคุณ
ณ จุดนี้คุณควรมีเซลล์แบบไดนามิก 'ทำงาน' ในคอลเล็กชันของคุณ ฉันยังไม่พบวิธีแก้ปัญหากล่องที่เพียงพอในระหว่างการทดสอบของฉันดังนั้นอย่าลังเลที่จะแสดงความคิดเห็นหากคุณมี มันยังรู้สึกเหมือนUITableView
ชนะการต่อสู้เพื่อปรับขนาด IMHO
คำเตือน
ต้องระวังมากว่าถ้าคุณกำลังใช้เซลล์ต้นแบบในการคำนวณ estimatedItemSize - นี้จะแตกถ้าคุณใช้ XIB ชั้นเรียนขนาด เหตุผลของเรื่องนี้ก็คือว่าเมื่อคุณโหลดมือถือของคุณจาก XIB Undefined
ระดับขนาดของมันจะได้รับการกำหนดค่าด้วย สิ่งนี้จะใช้งานไม่ได้กับ iOS 8 และใหม่กว่าตั้งแต่บน iOS 7 ขนาดของคลาสจะถูกโหลดตามอุปกรณ์ (iPad = ปกติ - ใด ๆ , iPhone = กะทัดรัด - อะไรก็ได้) คุณสามารถตั้งค่าประมาณItemSizeโดยไม่ต้องโหลด XIB หรือคุณสามารถโหลดเซลล์จาก XIB เพิ่มลงใน collectionView (สิ่งนี้จะตั้งค่า traitCollection) ดำเนินการเลย์เอาต์แล้วออกจาก superview หรือคุณอาจทำให้เซลล์แทนที่traitCollection
getter และคืนค่าคุณสมบัติที่เหมาะสม มันขึ้นอยู่กับคุณ.
แจ้งให้เราทราบหากฉันไม่ได้รับสิ่งใดหวังว่าฉันจะช่วยและโชคดีในการเขียนโค้ด