Für einen unserer Anwendungsbildschirme müssen wir ein UICollectionView
Inneres in a platzieren UITableViewCell
. Dies UICollectionView
hat eine dynamische Anzahl von Elementen, was zu einer Höhe führt, die ebenfalls dynamisch berechnet werden muss. Ich habe jedoch Probleme beim Versuch, die Höhe des Embedded zu berechnen UICollectionView
.
Unsere übergreifende UIViewController
wurde in Storyboards erstellt und verwendet das automatische Layout. Aber ich weiß nicht, wie ich die Höhe des UITableViewCell
basierend auf der Höhe des dynamisch erhöhen kann UICollectionView
.
Kann jemand einige Tipps oder Ratschläge geben, wie dies erreicht werden kann?
ios
uitableview
uicollectionview
Schattenmann
quelle
quelle
UITableViewCell
sich von seiner acutal Tableview?UICollectionView
UITableView
Antworten:
Die richtige Antwort ist JA , Sie KANN dies tun.
Ich bin vor einigen Wochen auf dieses Problem gestoßen. Es ist tatsächlich einfacher als Sie vielleicht denken. Legen Sie Ihre Zellen in NIBs (oder Storyboards) und stecken Sie sie fest, damit das automatische Layout die ganze Arbeit erledigt
Bei folgender Struktur:
Die Lösung besteht darin, das automatische Layout anzuweisen, zuerst die Größe der collectionViewCell, dann die Größe der Sammlungsansicht contentSize zu berechnen und als Größe Ihrer Zelle zu verwenden. Dies ist die UIView- Methode, die "die Magie macht":
Sie müssen hier die Größe der TableViewCell festlegen, in Ihrem Fall die contentSize der CollectionView.
CollectionViewCell
In der CollectionViewCell müssen Sie die Zelle bei jedem Modellwechsel anweisen, ein Layout zu erstellen (z. B. wenn Sie ein UILabel mit einem Text festlegen, muss die Zelle erneut ein Layout aufweisen).
TableViewCell
Die TableViewCell macht die Magie. Es verfügt über einen Auslass zu Ihrer Kollektion, ermöglicht das automatische Layout für Collection Zellen mit estimatedItemSize des UICollectionViewFlowLayout .
Der Trick besteht dann darin, die Größe Ihrer tableView-Zelle mit der systemLayoutSizeFittingSize ... -Methode festzulegen . (HINWEIS: iOS8 oder höher)
ANMERKUNG: Ich habe versucht, die Höhenmethode der delegierten Zelle in tableView zu
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
verwenden. Es ist jedoch zu spät für das automatische Layoutsystem, die CollectionView contentSize zu berechnen, und manchmal finden Sie möglicherweise Zellen mit falscher Größenänderung.TableViewController
Denken Sie daran, das automatische Layoutsystem für die tableView-Zellen in Ihrem TableViewController zu aktivieren :
KREDIT: @rbarbera hat geholfen, das zu klären
quelle
cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);
Dadurch wird eine lange Zelle mit einer langen CollectionView "simuliert", sodass die CollectionView die Größe aller ihrer Zellen berechnet. Andernfalls berechnete collectionView nur die sichtbaren Zellengrößen und stellte die Höhe der talbeViewCell falsch ein.systemLayoutSizeFittingSize
ich die Rahmenhöhe auf Maximum einstelle, stoße ich beim Neuladen der Zelle schnell auf ein Problem. Apps scheinen nach dem zu steckenself.collectionView.layoutIfNeeded()
. Ich habe es behoben, indem ich die Rahmenhöhe auf 1 anstatt auf die maximale Höhe eingestellt habe. Hoffe, es hilft, wenn jemand über dieses Problem stolpert.systemLayoutSizeFitting
, kehren Sie die Reihenfolge um, was in der Antwort aktuell angezeigt wird, so dass zuerstcollectionView.layoutIfNeeded()
läuft, danncollectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
Ich denke, meine Lösung ist viel einfacher als die von @PabloRomeu vorgeschlagene.
Schritt 1. Erstellen Sie eine Steckdose von
UICollectionView
bisUITableViewCell subclass
, wo sieUICollectionView
platziert ist. Lass es sein, der Name wird seincollectionView
Schritt 2. Fügen Sie IB für
UICollectionView
Höhenbeschränkungen hinzu und erstellen Sie auch einen Auslass fürUITableViewCell subclass
. Lass es sein, der Name wird seincollectionViewHeight
.Schritt 3.
tableView:cellForRowAtIndexPath:
Fügen Sie Code hinzu:quelle
collectionView
alle Seiten hinzuUITableViewCell
und setzetableView.estimatedRowHeight = 44;
undtableView.rowHeight = UITableViewAutomaticDimension;
Sowohl Tabellenansichten als auch Sammlungsansichten sind
UIScrollView
Unterklassen und möchten daher nicht in eine andere Bildlaufansicht eingebettet werden, da sie versuchen, Inhaltsgrößen zu berechnen, Zellen wiederzuverwenden usw.Ich empfehle Ihnen, für alle Ihre Zwecke nur eine Sammlungsansicht zu verwenden.
Sie können es in Abschnitte unterteilen und das Layout einiger Abschnitte als Tabellenansicht und andere als Sammlungsansicht "behandeln". Schließlich können Sie mit einer Sammlungsansicht nichts erreichen, was Sie mit einer Tabellenansicht erreichen können.
Wenn Sie ein grundlegendes Rasterlayout für Ihre Sammlungsansicht "Teile" haben, können Sie auch reguläre Tabellenzellen verwenden, um diese zu verarbeiten. Wenn Sie jedoch keine iOS 5-Unterstützung benötigen, sollten Sie Sammlungsansichten besser verwenden.
quelle
layoutAttributesForItemAtIndexPath
für verschiedene Abschnitte in meiner eigenen benutzerdefinierten Unterklasse von unterschiedlich zu reagierenUICollectionViewLayout
?Die Antwort von Pablo Romeu oben ( https://stackoverflow.com/a/33364092/2704206 ) hat mir bei meinem Problem sehr geholfen. Ich musste jedoch einige Dinge anders machen, damit dies für mein Problem funktioniert. Zunächst musste ich nicht
layoutIfNeeded()
so oft anrufen . Ich musste es nurcollectionView
in dersystemLayoutSizeFitting
Funktion aufrufen .Zweitens hatte ich automatische Layoutbeschränkungen für meine Sammlungsansicht in der Zelle der Tabellenansicht, um sie aufzufüllen. Also musste ich
targetSize.width
beim Einstellen dercollectionView.frame
Breite die vorderen und hinteren Ränder von den subtrahieren . Ich musste auch den oberen und unteren Rand zur Rückgabewerthöhe hinzufügenCGSize
.Um diese Einschränkungskonstanten zu erhalten, hatte ich die Möglichkeit, entweder Ausgänge für die Einschränkungen zu erstellen, ihre Konstanten fest zu codieren oder sie anhand eines Bezeichners nachzuschlagen. Ich habe mich für die dritte Option entschieden, um meine benutzerdefinierte Zellenklasse für die Tabellenansicht einfach wiederverwendbar zu machen. Am Ende war dies alles, was ich brauchte, um es zum Laufen zu bringen:
Als Hilfsfunktion zum Abrufen einer Einschränkung nach Bezeichner füge ich die folgende Erweiterung hinzu:
HINWEIS: Sie müssen den Bezeichner für diese Einschränkungen in Ihrem Storyboard oder überall dort festlegen, wo sie erstellt werden. Wenn sie keine 0-Konstante haben, spielt es keine Rolle. Wie in Pablos Antwort müssen Sie auch
UICollectionViewFlowLayout
als Layout für Ihre Sammlungsansicht verwenden.collectionView
Stellen Sie schließlich sicher, dass Sie das IBOutlet mit Ihrem Storyboard verknüpfen .Mit der obigen benutzerdefinierten Tabellenansichtszelle kann ich sie jetzt in jede andere Tabellenansichtszelle unterordnen, die eine Sammlungsansicht benötigt,
UICollectionViewDelegateFlowLayout
und dieUICollectionViewDataSource
Protokolle und implementieren lassen . Hoffe das ist hilfreich für jemand anderen!quelle
Ich habe alle Antworten durchgelesen. Dies scheint allen Fällen zu dienen.
quelle
Eine Alternative zur Lösung von Pablo Romeu besteht darin, UICollectionView selbst anzupassen, anstatt die Arbeit in der Zelle der Tabellenansicht auszuführen.
Das zugrunde liegende Problem besteht darin, dass eine Sammlungsansicht standardmäßig keine intrinsische Größe hat und daher das automatische Layout nicht über die zu verwendenden Dimensionen informieren kann. Sie können dies beheben, indem Sie eine benutzerdefinierte Unterklasse erstellen, die eine nützliche Eigengröße zurückgibt.
Erstellen Sie eine Unterklasse von UICollectionView und überschreiben Sie die folgenden Methoden
(Sie sollten auch die zugehörigen Methoden überschreiben: reloadSections, reloadItemsAtIndexPaths auf ähnliche Weise wie reloadData ())
Durch Aufrufen von layoutIfNeeded wird die Sammlungsansicht gezwungen, die Inhaltsgröße neu zu berechnen, die dann als neue intrinsische Größe verwendet werden kann.
Außerdem müssen Sie Änderungen an der Ansichtsgröße (z. B. bei Gerätedrehung) im Tabellenansichts-Controller explizit behandeln
quelle
Ich hatte kürzlich das gleiche Problem und habe fast jede Lösung in den Antworten ausprobiert. Einige davon haben funktioniert, andere waren nicht mein Hauptanliegen beim @ PabloRomeu- Ansatz. Wenn Sie andere Inhalte in der Zelle haben (außer der Sammlungsansicht), Sie müssen ihre Höhen und die Höhen ihrer Einschränkungen berechnen und das Ergebnis zurückgeben, um das richtige automatische Layout zu erhalten, und ich möchte die Dinge nicht manuell in meinem Code berechnen. Hier ist also die Lösung, die für mich ohne manuelle Berechnungen in meinem Code gut funktioniert hat.
In der
cellForRow:atIndexPath
Tabellenansicht mache ich folgendes:Ich denke, was hier passiert, ist, dass ich die Tabellenansichtszelle zwinge, ihre Höhe anzupassen, nachdem die Höhe der Sammlungsansicht berechnet wurde. (nach Angabe des CollectionView-Datums an die Datenquelle)
quelle
Ich würde der Sammlungsansichtsklasse eine statische Methode hinzufügen, die eine Größe basierend auf dem Inhalt zurückgibt, den sie haben wird. Verwenden Sie dann diese Methode in
heightForRowAtIndexPath
, um die richtige Größe zurückzugeben.Beachten Sie auch, dass Sie beim Einbetten dieser Art von viewControllern ein seltsames Verhalten feststellen können. Ich habe es einmal gemacht und hatte einige seltsame Gedächtnisprobleme, die ich nie gelöst habe.
quelle
Vielleicht ist meine Variante nützlich; Ich habe diese Aufgabe in den letzten zwei Stunden entschieden. Ich gebe nicht vor, dass es 100% korrekt oder optimal ist, aber meine Fähigkeiten sind noch sehr klein und ich würde gerne Kommentare von Experten hören. Danke dir. Ein wichtiger Hinweis: Dies funktioniert für statische Tabellen - es wird von meiner aktuellen Arbeit angegeben. Ich verwende also nur viewWillLayoutSubviews von tableView . Und ein bisschen mehr.
quelle
Der einfachste Ansatz, den ich bisher gefunden habe: Credits to @igor Antwort oben,
Fügen Sie dies einfach in Ihre tableviewcell-Klasse ein
und natürlich ändern Sie das Collectionviewoutlet mit Ihrem Outlet in der Klasse der Zelle
quelle
Ich bekomme eine Idee von @Igor post und investiere meine Zeit dafür schnell in mein Projekt
Einfach vorbei in deinem
Ergänzung: Wenn Ihre UICollectionView beim Laden von Zellen abgehackt ist.
quelle
Pablos Lösung funktionierte für mich nicht sehr gut, ich hatte seltsame visuelle Effekte (die collectionView wurde nicht richtig angepasst).
Was funktionierte, war das Anpassen der Höhenbeschränkung der collectionView (als NSLayoutConstraint) an die collectionView contentSize während
layoutSubviews()
. Dies ist die Methode, die aufgerufen wird, wenn Autolayout auf die Zelle angewendet wird.quelle
In Ihrem UITableViewDelegate:
Ersetzen Sie itemCount und CollectionViewCellHeight durch die realen Werte. Wenn Sie ein Array von Arrays haben, könnte itemCount sein:
Oder Wasauchimmer.
quelle
collectionViewCellHeight
bevor es rendert.1.Erstellen Sie eine Dummy-Zelle.
2.Verwenden Sie die collectionViewContentSize-Methode in UICollectionViewLayout von UICollectionView unter Verwendung aktueller Daten.
quelle
Sie können die Höhe der Sammlung berechnen auf der Grundlage ihrer Eigenschaften wie
itemSize
,sectionInset
,minimumLineSpacing
,minimumInteritemSpacing
, wenn IhrcollectionViewCell
den Rand einer Regel.quelle