Zaktualizowano dla Swift 5
preferredLayoutAttributesFittingAttributes
zmieniono nazwę na preferredLayoutAttributesFitting
i używaj automatycznego dostosowywania
Zaktualizowano dla Swift 4
systemLayoutSizeFittingSize
przemianowany na systemLayoutSizeFitting
Zaktualizowano dla iOS 9
Po tym, jak moje rozwiązanie GitHub zepsuło się pod iOS 9, w końcu miałem czas na pełne zbadanie problemu. Zaktualizowałem teraz repozytorium, aby zawierało kilka przykładów różnych konfiguracji dla komórek samokierujących. Doszedłem do wniosku, że komórki samoklejające są świetne w teorii, ale w praktyce są nieuporządkowane. Należy zachować ostrożność podczas wybierania komórek samokierujących.
TL; DR
Sprawdź mój projekt GitHub
Komórki samopoziomujące są obsługiwane tylko z układem przepływu, więc upewnij się, że tego używasz.
Istnieją dwie rzeczy, które musisz skonfigurować, aby komórki o własnych rozmiarach działały.
1. Ustaw estimatedItemSize
naUICollectionViewFlowLayout
Układ przepływu stanie się dynamiczny z natury po ustawieniu estimatedItemSize
właściwości.
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
2. Dodaj obsługę zmiany rozmiaru w podklasie komórki
Występuje w 2 smakach; Auto-układ lub niestandardowe zastąpienie preferredLayoutAttributesFittingAttributes
.
Twórz i konfiguruj komórki za pomocą automatycznego układu
Nie będę wchodził w szczegóły na ten temat, ponieważ istnieje genialny post SO dotyczący konfigurowania ograniczeń dla komórki. Bądź ostrożny, że Xcode 6 złamał wiele rzeczy w iOS 7, więc jeśli wspierasz iOS 7, musisz zrobić takie rzeczy, jak upewnić się, że maska autoresizingMas jest ustawiona na contentView komórki i że granice contentView są ustawione jako granice komórki, gdy komórka jest załadowana (tjawakeFromNib
.).
Należy pamiętać, że komórka musi być poważniej ograniczona niż komórka widoku tabeli. Na przykład, jeśli chcesz, aby szerokość była dynamiczna, twoja komórka potrzebuje ograniczenia wysokości. Podobnie, jeśli chcesz, aby wysokość była dynamiczna, będziesz potrzebować ograniczenia szerokości do swojej komórki.
Implementuj preferredLayoutAttributesFittingAttributes
w niestandardowej komórce
Po wywołaniu tej funkcji widok został już skonfigurowany z zawartością (tj. cellForItem
Został wywołany). Zakładając, że ograniczenia zostały odpowiednio ustawione, możesz mieć taką implementację:
//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
}
UWAGA W systemie iOS 9 zachowanie zmieniło się nieco, co może spowodować awarie implementacji, jeśli nie będziesz ostrożny (zobacz więcej tutaj ). Po wdrożeniu preferredLayoutAttributesFittingAttributes
musisz upewnić się, że zmienisz ramkę atrybutów układu tylko raz. Jeśli tego nie zrobisz, układ wywoła twoją implementację w nieskończoność i ostatecznie ulegnie awarii. Jednym z rozwiązań jest buforowanie obliczonego rozmiaru w komórce i unieważnianie go za każdym razem, gdy ponownie użyjesz komórki lub zmienisz jej zawartość, tak jak zrobiłem to z tą isHeightCalculated
właściwością.
Poznaj swój układ
W tym momencie powinieneś mieć „funkcjonujące” dynamiczne komórki w swojej kolekcjiViewView. Nie znalazłem jeszcze gotowego rozwiązania wystarczającego podczas moich testów, więc możesz to skomentować, jeśli tak. Nadal wydaje się, że UITableView
wygrywa bitwę o dynamiczne zmiany rozmiaru IMHO.
Ostrzeżenia
Pamiętaj, że jeśli używasz prototypowych komórek do obliczania oszacowanegoItemSize - to się zepsuje, jeśli twój XIB używa klas wielkości . Powodem tego jest to, że po załadowaniu komórki z XIB zostanie skonfigurowana klasa wielkości Undefined
. Zostanie to zerwane tylko w systemie iOS 8 i nowszym, ponieważ w systemie iOS 7 klasa wielkości zostanie załadowana na podstawie urządzenia (iPad = zwykły-dowolny, iPhone = kompaktowy-dowolny). Możesz ustawić oszacowaną wartość Bez ładowania XIB lub załadować komórkę z XIB, dodać ją do collectionView (spowoduje to ustawienie funkcji traitCollection), wykonać układ, a następnie usunąć z superwizji. Alternatywnie możesz również sprawić, że twoja komórka zastąpi traitCollection
getter i zwróci odpowiednie cechy. To zależy od Ciebie.
Daj mi znać, jeśli coś przeoczyłem, mam nadzieję, że pomogłem i powodzenia w kodowaniu