Đã cập nhật cho Swift 5
preferredLayoutAttributesFittingAttributes
đổi tên thành preferredLayoutAttributesFitting
và sử dụng kích thước tự động
Đã cập nhật cho Swift 4
systemLayoutSizeFittingSize
đổi tên thành systemLayoutSizeFitting
Đã cập nhật cho iOS 9
Sau khi thấy giải pháp GitHub của tôi bị hỏng trong iOS 9, cuối cùng tôi cũng có thời gian để điều tra vấn đề đầy đủ. Bây giờ tôi đã cập nhật repo để bao gồm một số ví dụ về các cấu hình khác nhau cho các ô tự kích thước. Kết luận của tôi là các tế bào tự kích thước là lý thuyết tuyệt vời nhưng lộn xộn trong thực tế. Một lời cảnh báo khi tiến hành với các tế bào tự kích thước.
TL; DR
Kiểm tra dự án GitHub của tôi
Các ô tự kích thước chỉ được hỗ trợ với bố cục luồng, vì vậy hãy chắc chắn rằng đó là những gì bạn đang sử dụng.
Có hai điều bạn cần thiết lập để các ô tự kích thước hoạt động.
1. Đặt estimatedItemSize
trênUICollectionViewFlowLayout
Bố cục dòng chảy sẽ trở nên năng động trong tự nhiên khi bạn đặt thuộc estimatedItemSize
tính.
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
2. Thêm hỗ trợ cho kích thước trên lớp con di động của bạn
Điều này có 2 hương vị; Tự động bố trí hoặc ghi đè tùy chỉnh của preferredLayoutAttributesFittingAttributes
.
Tạo và cấu hình các ô với Bố cục tự động
Tôi sẽ không đi vào chi tiết về điều này vì có một bài viết SO tuyệt vời về cấu hình các ràng buộc cho một ô. Hãy cảnh giác rằng Xcode 6 đã phá vỡ một loạt các thứ với iOS 7, vì vậy, nếu bạn hỗ trợ iOS 7, bạn sẽ cần làm những thứ như đảm bảo autoresizingMask được đặt trên contentView của cell và giới hạn của contentView được đặt làm giới hạn của ô khi tế bào được tải (tức là awakeFromNib
).
Điều bạn cần lưu ý là ô của bạn cần bị ràng buộc nghiêm trọng hơn so với Ô xem bảng. Ví dụ, nếu bạn muốn chiều rộng của bạn là động thì ô của bạn cần một ràng buộc về chiều cao. Tương tự như vậy, nếu bạn muốn chiều cao là động thì bạn sẽ cần một ràng buộc về chiều rộng cho ô của bạn.
Thực hiện preferredLayoutAttributesFittingAttributes
trong ô tùy chỉnh của bạn
Khi chức năng này được gọi, chế độ xem của bạn đã được định cấu hình với nội dung (tức là cellForItem
đã được gọi). Giả sử các ràng buộc của bạn đã được đặt một cách thích hợp, bạn có thể có một triển khai như thế này:
//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
}
LƯU Ý Trên iOS 9, hành vi đã thay đổi một chút có thể gây ra sự cố khi triển khai nếu bạn không cẩn thận (Xem thêm tại đây ). Khi bạn triển khai, preferredLayoutAttributesFittingAttributes
bạn cần đảm bảo rằng bạn chỉ thay đổi khung thuộc tính bố cục của bạn một lần. Nếu bạn không làm điều này, bố cục sẽ gọi việc thực hiện của bạn vô thời hạn và cuối cùng sẽ sụp đổ. Một giải pháp là lưu trữ kích thước được tính toán trong ô của bạn và vô hiệu hóa điều này bất cứ khi nào bạn sử dụng lại ô hoặc thay đổi nội dung của nó như tôi đã làm với thuộc isHeightCalculated
tính.
Trải nghiệm bố cục của bạn
Tại thời điểm này, bạn nên có các ô động 'hoạt động' trong bộ sưu tập của bạn. Tôi chưa tìm thấy giải pháp vượt trội trong các thử nghiệm của mình, vì vậy hãy bình luận nếu bạn có. Nó vẫn cảm thấy như UITableView
chiến thắng trong cuộc chiến về kích thước IMHO năng động.
Hãy cẩn thận
Hãy lưu ý rằng nếu bạn đang sử dụng các ô nguyên mẫu để tính toán Ước tính kích thước - điều này sẽ bị hỏng nếu XIB của bạn sử dụng các lớp kích thước . Lý do cho điều này là khi bạn tải ô của mình từ XIB, lớp kích thước của nó sẽ được cấu hình Undefined
. Điều này sẽ chỉ bị hỏng trên iOS 8 trở lên vì trên iOS 7, lớp kích thước sẽ được tải dựa trên thiết bị (iPad = Chính quy-Bất kỳ, iPhone = Nhỏ gọn-Bất kỳ). Bạn có thể đặt ước tính kích thước mà không cần tải XIB hoặc bạn có thể tải ô từ XIB, thêm nó vào bộ sưu tập (điều này sẽ đặt traitCollection), thực hiện bố cục và sau đó xóa nó khỏi giám sát. Ngoài ra, bạn cũng có thể làm cho tế bào của bạn ghi đè lên traitCollection
getter và trả về các đặc điểm thích hợp. Tuỳ bạn.
Hãy cho tôi biết nếu tôi bỏ lỡ bất cứ điều gì, hy vọng tôi đã giúp và chúc may mắn mã hóa