W pionie UICollectionView
,
Czy można mieć komórki o pełnej szerokości , ale zezwolić na kontrolowanie wysokości dynamicznej przez autoukładanie ?
To wydaje mi się być może „najważniejszym pytaniem w iOS, na które nie ma dobrej odpowiedzi”.
Ważny:
Zwróć uwagę, że w 99% przypadków, aby uzyskać komórki o pełnej szerokości + autoukładanie dynamicznej wysokości, po prostu użyj widoku tabeli. To jest takie proste.
Więc jaki jest przykład, gdzie potrzebujesz widoku kolekcji?
Widoki kolekcji są niewiarygodnie potężniejsze niż widoki tabel.
Jeden prosty przykład, w którym w rzeczywistości musisz użyć widoku kolekcji, aby uzyskać komórki o pełnej szerokości + automatycznie układającą się dynamiczną wysokość:
Jeśli animujesz między dwoma układami w widoku kolekcji. Na przykład układ między 1 a 2 kolumnami, gdy urządzenie się obraca.
To powszechny i normalny idiom w iOS. Niestety można to osiągnąć tylko poprzez rozwiązanie problemu przedstawionego w tej kontroli jakości. : - /
źródło
SpringDamping
iinitialSpringVelocity
) w tabeli Cell ..... spójrz na tę listę Bouncy używając tableView ,,,, pastebin.com/pFRQhkrX możesz animowaćTableViewCell
tabelę wwillDisplayCell:(UITableViewCell *)cell
metodzie delgate @Fattie możesz zaakceptować odpowiedź, która rozwiązała Twój problem, aby pomóc innym, którzy szukają tego samego problemuOdpowiedzi:
1. Rozwiązanie dla iOS 13+
Dzięki Swift 5.1 i iOS 13 możesz użyć obiektów układu kompozycyjnego w celu rozwiązania problemu.
Poniższy kompletny przykładowy kod pokazuje, jak wyświetlić multilinię
UILabel
w pełnej szerokościUICollectionViewCell
:CollectionViewController.swift
HeaderView.swift
CustomCell.swift
Oczekiwany wyświetlacz:
2. Rozwiązanie dla iOS 11+
W Swift 5.1 i iOS 11 możesz podklasować
UICollectionViewFlowLayout
i ustawić jegoestimatedItemSize
właściwość naUICollectionViewFlowLayout.automaticSize
(to mówi systemowi, że chcesz zająć się autorezacjąUICollectionViewCell
). Będziesz wtedy musiał nadpisaćlayoutAttributesForElements(in:)
ilayoutAttributesForItem(at:)
ustawić szerokość komórek. Na koniec będziesz musiał nadpisaćpreferredLayoutAttributesFitting(_:)
metodę swojej komórki i obliczyć jej wysokość.Poniższy kompletny kod pokazuje, jak wyświetlić multilinię
UILabel
wewnątrz pełnej szerokościUIcollectionViewCell
(ograniczone przezUICollectionView
bezpieczny obszar iUICollectionViewFlowLayout
wstawki):CollectionViewController.swift
CustomFlowLayout.swift
HeaderView.swift
CustomCell.swift
Oto kilka alternatywnych implementacji
preferredLayoutAttributesFitting(_:)
:Oczekiwany wyświetlacz:
źródło
Problem
Szukasz automatycznej wysokości, a także chcesz mieć pełną szerokość, nie jest możliwe uzyskanie obu w użyciu
UICollectionViewFlowLayoutAutomaticSize
.Chcesz to zrobić,
UICollectionView
więc poniżej jest rozwiązanie dla Ciebie.Rozwiązanie
1. Jeśli masz tylko
UILabel
wCollectionViewCell
niż ustawiononumberOfLines=0
i obliczono oczekiwaną wysokośćUIlable
, przekaż wszystkie trzy parametry2. Jeśli twój
CollectionViewCell
zawiera tylkoUIImageView
i jeśli przypuszczalnie ma być dynamiczny w Height, niż potrzebujesz uzyskać wysokośćUIImage
(UIImageView
musisz miećAspectRatio
ograniczenia)3. Jeśli zawiera oba, oblicz ich wysokość i zsumuj je.
1. Dodaj
UICollectionViewDelegateFlowLayout
delegata w swoim viewController2. Zaimplementuj metodę delegata
Mam nadzieję, że to ci pomoże.
źródło
return CGSize(width: view.frame.width/2, height: expectedHeight)
również zachowaj Padding na koncie, niż zwróć szerokość, w przeciwnym razie dwie komórki nie zmieściłyby się w jednym wierszu.Istnieje kilka sposobów rozwiązania tego problemu.
Jednym ze sposobów jest nadanie układowi przepływu widoku kolekcji szacunkowego rozmiaru i obliczenie rozmiaru komórki.
Uwaga: jak wspomniano w komentarzach poniżej, od iOS 10 nie musisz już podawać i szacować rozmiaru, aby wywołać wywołanie komórek
func preferredLayoutAttributesFitting(_ layoutAttributes:)
. Wcześniej (iOS 9) wymagało podania szacunkowego rozmiaru, jeśli chcesz zapytać o komórki prefferedLayoutAttributes.(zakładając, że używasz scenorysów, a widok kolekcji jest połączony przez IB)
W przypadku prostych komórek zwykle wystarczy. Jeśli rozmiar jest nadal nieprawidłowy, w komórce widoku kolekcji można nadpisaćfunc preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes
, co zapewni dokładniejszą kontrolę nad rozmiarem komórki. Uwaga: nadal musisz podać szacunkowy rozmiar układu przepływu .Następnie zastąp,
func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes
aby zwrócić prawidłowy rozmiar.Alternatywnie możesz użyć komórki rozmiaru, aby obliczyć rozmiar komórki w
UICollectionViewDelegateFlowLayout
.Chociaż nie są to doskonałe przykłady gotowe do produkcji, powinny one pomóc Ci zacząć we właściwym kierunku. Nie mogę powiedzieć, że jest to najlepsza praktyka, ale działa to dla mnie, nawet w przypadku dość złożonych komórek zawierających wiele etykiet, które mogą, ale nie muszą, zawijać się w wiele wierszy.
źródło
preferredLayoutAttributesFitting
. Następnie dodałem własne ograniczenie we wspomnianej funkcji, wiążące się ze stałym wymiarem z assessmentItemSize, FWIW, zobacz moją odpowiedź poniżej.Znalazłem całkiem proste rozwiązanie tego problemu: wewnątrz mojej CollectionViewCell otrzymałem UIView (), który jest właściwie tylko tłem. Aby uzyskać pełną szerokość, po prostu ustawiłem następujące kotwice
„Magia” dzieje się w pierwszej linii. Ustawiłem widthAnchor dynamicznie na szerokość ekranu. Ważne jest również odjęcie wstawek z CollectionView. W przeciwnym razie komórka się nie pojawi. Jeśli nie chcesz mieć takiego widoku tła, po prostu uczyń go niewidocznym.
FlowLayout używa następujących ustawień
Wynikiem jest komórka o pełnej szerokości i dynamicznej wysokości.
źródło
PRACUJĄCY!!! Przetestowano na IOS: 12.1 Swift 4.1
Mam bardzo proste rozwiązanie, które po prostu działa bez łamania ograniczeń.
My ViewControllerClass
Klasa CustomCell:
Głównym składnikiem jest systemLayoutSizeFitting funkcja w Customcell. Musimy także ustawić szerokość widoku wewnątrz komórki z ograniczeniami.
źródło
Musisz dodać ograniczenie szerokości do CollectionViewCell
źródło
Zestaw
estimatedItemSize
układu przepływu:Zdefiniuj ograniczenie szerokości w komórce i ustaw je tak, aby było równe szerokości superview:
Pełny przykład
Przetestowano na iOS 11.
źródło
Osobiście znalazłem najlepsze sposoby na uzyskanie UICollectionView, w którym AutoLayout określa rozmiar, podczas gdy każda komórka może mieć inny rozmiar, polega na zaimplementowaniu funkcji UICollectionViewDelegateFlowLayout sizeForItemAtIndexPath podczas używania rzeczywistej komórki do pomiaru rozmiaru.
Mówiłem o tym w jednym z moich postów na blogu
Mam nadzieję, że ten pomoże Ci osiągnąć to, czego chcesz. Nie jestem pewien w 100%, ale uważam, że w przeciwieństwie do UITableView, w którym można faktycznie uzyskać w pełni automatyczną wysokość komórek, używając funkcji AutoLayout w połączeniu z
UICollectionView nie ma takiego sposobu, aby pozwolić AutoLayout określić rozmiar, ponieważ UICollectionViewCell niekoniecznie wypełnia całą szerokość ekranu.
Ale oto pytanie do Ciebie : jeśli potrzebujesz komórek o pełnej szerokości ekranu, dlaczego w ogóle zawracasz sobie głowę używaniem UICollectionView zamiast starego dobrego UITableView, który jest dostarczany z komórkami o automatycznym rozmiarze?
źródło
Zgodnie z moim komentarzem do odpowiedzi Erica, moje rozwiązanie jest bardzo podobne do jego, ale musiałem dodać ograniczenie w preferowanym rozmiarze dla ... w celu ograniczenia do stałego wymiaru.
To pytanie ma wiele duplikatów, szczegółowo odpowiedziałem na nie tutaj i przedstawiłem tutaj działającą przykładową aplikację.
źródło
Nie jestem pewien, czy kwalifikuje się to jako „naprawdę dobra odpowiedź”, ale właśnie tego używam, aby to osiągnąć. Mój układ przepływu jest poziomy i próbuję dopasować szerokość za pomocą automatycznego układu, więc jest podobny do twojej sytuacji.
Następnie w kontrolerze widoku, w którym ograniczenie autoukładu jest modyfikowane, uruchamiam NSNotification.
W mojej podklasie UICollectionView nasłuchuję tego powiadomienia:
i unieważnić układ:
Powoduje
sizeForItemAt
to ponowne wywołanie przy użyciu nowego rozmiaru widoku kolekcji. W twoim przypadku powinna być w stanie zaktualizować, biorąc pod uwagę nowe ograniczenia dostępne w układzie.źródło
Na twoim
viewDidLayoutSubviews
ustaw naestimatedItemSize
pełną szerokość (układ odwołuje się do obiektu UICollectionViewFlowLayout):W komórce upewnij się, że ograniczenia dotykają zarówno góry, jak i dołu komórki (poniższy kod używa Kartografii, aby uprościć ustawianie ograniczeń, ale możesz to zrobić za pomocą NSLayoutConstraint lub IB, jeśli chcesz):
Voila, twoje komórki będą teraz automatycznie rosły!
źródło
Żadne z rozwiązań nie działało dla mnie, ponieważ potrzebuję dynamicznej szerokości, aby dostosować szerokość między iPhone'ami.
źródło
Od iOS 10 mamy do tego nowy interfejs API w układzie przepływu.
Wszystko co musisz zrobić, to ustawić swój
flowLayout.estimatedItemSize
do nowej stałej,UICollectionViewFlowLayoutAutomaticSize
.Źródło
źródło
AutoLayout może służyć do automatycznego określania rozmiaru komórek w CollectionView w 2 prostych krokach:
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
collectionView(:cellForItemAt:)
aby ograniczyć szerokość contentView do width of collectionView.To wszystko, uzyskasz pożądany efekt. Zapoznaj się z poniższymi streszczeniami, aby uzyskać pełny kod:
Referencje / kredyty:
Zrzut ekranu:
źródło
Musisz odziedziczyć klasę UICollectionViewDelegateFlowLayout w swojej collectionViewController. Następnie dodaj funkcję:
Używając tego, masz rozmiar szerokości ekranu.
Teraz masz collectionViewController z wierszami jako tableViewController.
Jeśli chcesz, aby wysokość każdej komórki była dynamiczna, być może powinieneś utworzyć niestandardowe komórki dla każdej potrzebnej komórki.
źródło