Erstellen von UITableView mit eingebetteter UICollectionView mit UITableViewAutomaticDimension

9

Ich möchte ein UITableView mit Titel-Label und eingebettetem UICollectionView (welches die Größe kennt) mit einigen Icons erstellen, die UITableViewAutomaticDimension verwenden. Das Problem ist UITableView hat ein Problem mit der Berechnung der Zellenhöhe, wenn ich UICollectionView drin habe. Ich muss einen UITableView scrollen, um Größen neu zu berechnen. Aber selbst dann hat es Probleme mit der Höhe (es ist zu groß, wenn es von einem größeren wiederverwendet wurde). Darüber hinaus sind die Symbole in UICollectionView nicht bekannt, aber sie sollen vom Server geladen werden.

Ich habe auch versucht, eine height constraint für UICollectionView zu erstellen, aber auf diese Weise bekomme ich "Constraint nicht gleichzeitig erfüllen", verursacht durch einen Konflikt mit UIView-Encapsulated-Layout-Height und meine eigene Constraint wird trotzdem entfernt.

Ich habe ein GitHub-Repository mit einem Beispielprojekt erstellt (ich habe es so einfach wie möglich gemacht):

Ссылка

    
Makalele 04.01.2018, 10:46
quelle

5 Antworten

8

Da du sehr viel in cellForRow machst, braucht es Zeit um fertig zu sein und wenn du scrollst wird es nicht richtig angezeigt

Überprüfen Sie folgende Dinge.

ViewController.swift

In View wurde geladen

Fügen Sie tableView.rowHeight = UITableViewAutomaticDimension

hinzu

und ersetzen Sie diese Methode

%Vor%

FooTableViewCell.swift

%Vor%

Und ich habe StackView Form von Ihrem Storyboard entfernt und gebe nur die führenden, abschließenden, oberen und unteren Beschränkungen vor (Nichts kompliziertes)

Hier wird ausgegeben

Ich hoffe, es ist hilfreich für Sie

BEARBEITEN / AKTUALISIEREN

Sie haben viele Probleme in Ihrem Demoprojekt. Ich habe in Ihrem Demo-Projekt viele Änderungen vorgenommen.

Kopieren und fügen Sie XML in das Storyboard ein.

VERBINDEN SIE NICHT, HÖHENKONSTRAINT ZU VERBINDEN

Hier ist das komplette Storyboard XML

%Vor%

FOOTableviewCell.swift

%Vor%

IconCollectionView.swift

%Vor%

ViewController.Swift

%Vor%

AUSGABE

BEARBEITEN / AKTUALISIEREN 2

Ich wusste nicht über Orientierungsunterstützung und iPad-Unterstützung.

Jetzt, wenn sich die Ausrichtung ändert, müssen wir die Sammlungsansicht neu anordnen.

Also Logik ist

Gesamtzahl der Elemente + 1 (+ 1 aufgrund dieses Plus-Symbols)

Artikelgröße * (Gesamtzahl Artikel / 3) .rounded

Angenommen, Sie haben 7 Elemente

so ist die Artikelgröße 93 (Pro Zeile) * (8/3) .rounded = 279

Hier müssen Sie also einige fest codierte Werte gemäß Ihren Anforderungen für den iPad- und Landscape-Modus verwalten. Momentan betrachte ich 3 Objekte pro Zeile wie das iPhone Design.

Hier ist die Nummer der fest codierten Zelle 3 Sie können Ihre eigenen verwalten.

Schritt 1:

Fügen Sie folgende Methode in viewContorller.swift

hinzu %Vor%

Ersetzen Sie cellForRowAtIndexPath

%Vor%

Und

%Vor%

In TableViewCell

%Vor%

und

%Vor%     
Prashant Tukadiya 11.01.2018, 13:51
quelle
2

Ich denke, du musst estimatedHeightForRowAt implementieren, also statt der Methode

%Vor%

Verwenden Sie die folgende Methode:

%Vor%

Das sollte funktionieren, probier es aus!

    
torap 08.01.2018 17:05
quelle
2

UICollectionView selbst hat keine intrinsische Inhaltsgröße, daher müssen Sie eine explizite Höhenbeschränkung dafür erstellen, wie Sie sagen.

Wenn das Layout scheint zu arbeiten, aber Sie erhalten unerfüllbare Einschränkungen mit UIView-Encapsulated-Layout-Height , dann lesen Sie die folgenden.

Das ist ein Ergebnis davon, wie UITableViewAutomaticDimension funktioniert - es setzt die Höhe der Zelle basierend auf einem Standardwert (ich weiß immer noch nicht, wie es diesen Wert bekommt), dann benutzt man automatisches Layout um die Höhe zu berechnen, die deine Zelle haben möchte, und aktualisiert dann UIView-Encapsulated-Layout-Height so, dass sie der neuen Höhe entspricht. Aber dabei geraten Ihre Constraints und die UIView-Encapsulated-Layout-Height Constraint in Konflikt. Die Lösung besteht darin, die Priorität einer Ihrer Einschränkungen auf collectionViewHeightConstraint.priority = UILayoutPriority(rawValue: 999) zu setzen. Auf diese Weise werden die Constraints nicht unterbrochen und das automatische Layout funktioniert ohne Warnungen. Beachten Sie, dass am Ende UIView-Encapsulated-Layout-Height auf die richtige Höhe aktualisiert wird, so dass das Absenken der Priorität das Layout nicht beeinträchtigt. Siehe meine Antwort zu einer ähnlichen Frage als Referenz.

BEARBEITEN

Ich habe Ihr Projekt gegabelt, repariert und eine Pull-Anforderung erstellt (siehe GitHub).

Das Hauptproblem, das ich glaube, war ein sehr trivialer Fehler. Sie haben bars.count verwendet, um die innere Größe der Sammlung zu berechnen, aber am Ende hatten Sie bars.count + 1 Elemente in der Sammlung (das Symbol +). Wenn das Symbol + allein in eine neue Zeile eingefügt werden musste, schien das Layout nicht zu funktionieren.

Ändern Sie einfach

%Vor%

bis

%Vor%

in intrinsicContentSize der IconsCollectionView .

Es gab noch andere Dinge, die ich ändern würde, und ich habe es im Projekt geändert - in Ihrem Zellprototyp in Storyboards.

Zuerst habe ich diese explizite Einschränkung für die Höhe der Sammlungsgruppe auf 88 Punkte reduziert. Sie haben eine interne Größe, also brauchen Sie das nicht (wenn Storyboards sich beschweren, haben sie nichts dagegen, sie wissen nicht, dass Sie die tatsächliche Größe implementiert haben.

Zweitens war die Schaltfläche am unteren Rand der Zelle nicht beschränkt. Daher könnte die Berechnung der Zellenhöhe nicht funktionieren (Sie möchten, dass sich die Zelle selbst an ihren Inhalt anpasst, also müssen Sie alle Seiten der Zelle auf ihren Inhalt beschränken). Aber das war vielleicht ein Ergebnis der Ratschläge anderer, weil ich glaube, dass ältere Commits es funktionierten.

Drittens, eine kleine Anmerkung, ist die Art, wie Sie superviewWidth verwendet haben, um die Größe zu berechnen. Ich änderte es in selfView und änderte die Art, wie sein Wert berechnet wurde. Denn am Ende ist die Breite der Sammlungsansicht nicht gleich der Zellenbreite, sondern der Zellenbreite -16. Das liegt daran, dass collectionView gezwungen war, 8 Punkte von der linken Seite der Zelle contentView und 8 Punkte von der rechten Seite der Zelle contentView zu starten. Obwohl das nicht das Hauptproblem war, könnte es später einige Probleme verursachen.

Schließlich habe ich Ihnen einen Kommentar in Ihrem asynchronen Laden der Artikel hinterlassen. Wenn Sie es asynchron laden, wird die Zelle höchstwahrscheinlich angezeigt, bevor Sie Ihre Daten zurückbekommen, und Sie sollten das TableView aktualisieren, um es an neu geladene Daten anzupassen. Im Prinzip ist das das Gleiche wie das dynamische Erweitern und Zusammenfalten von Zellen - dafür verweise ich Sie auf meine Antwort auf diese Frage .

    
Milan Nosáľ 12.01.2018 12:16
quelle
1

Ich habe den Quellcode heruntergeladen und das Problem behoben. Ihr Code ist perfekt zum Einstellen der Zellengröße, das Problem liegt im Spaltenflusslayout. Sie haben 4 Zellen hintereinander angezeigt, aber laut Ihrem Quellcode wurden nur 3 Zellen angezeigt. Ich habe tiefer hinein gegriffen und herausgefunden, dass die Anzahl der Zellen in Ihrer "intrinsicContentSize" in der Icon-Sammlung falsch berechnet wird Aussicht. Die Breite der Superansicht, die Sie in der Flow-Layout-Funktion übergeben, verursacht ein Problem. Ich denke, es gab einige Abstandsprobleme für die Breite. Also hier ist, wie mein neuer Code aussieht:

%Vor%

Ich habe nur diese beiden Funktionen geändert und Ihr Code hat einwandfrei funktioniert.

Wenn du Quellcode willst, kann ich es auch auf git schieben. Hoffe das hilft dir aus!

    
Pallavi Srikhakollu 11.01.2018 16:21
quelle
1

Das Problem ist:

%Vor%

Also berechnet das TableView nicht die richtigen Zellenhöhen.

Die Lösung besteht darin, deinem collectionView eine Höhe zu geben, während du die Icons abrufst. Wenn der Abruf abgeschlossen ist, bitten Sie Ihre tableView , die entsprechende Zeile erneut zu laden. Daher sollten Sie Ihre Höhenberechnung auf dem Layout Ihrer collectionView und nicht auf contenSize height basieren: contenSize von collectionView ist möglicherweise falsch, weil reloadData tatsächlich asynchron ist .

    
GaétanZ 09.01.2018 09:19
quelle