In einer Vertikalen UICollectionView
,
Ist es möglich, Zellen mit voller Breite zu haben , aber die dynamische Höhe durch Autolayout zu steuern ?
Dies scheint mir die "wichtigste Frage in iOS ohne wirklich gute Antwort" zu sein.
Wichtig:
Beachten Sie, dass in 99% der Fälle einfach eine Tabellenansicht verwendet werden muss, um Zellen mit voller Breite + dynamische Höhe für das automatische Auslegen zu erzielen . So einfach ist das.
Was ist ein Beispiel dafür, wo Sie eine Sammlungsansicht benötigen?
Sammlungsansichten sind unglaublich leistungsfähiger als Tabellenansichten.
Ein einfaches Beispiel , wo man tatsächlich hat eine Sammlung Ansicht verwenden, um volle Breite Zellen zu erreichen + automatisches Layout dynamische Höhe:
Wenn Sie animieren zwischen zwei Layouts in einer Sammlungsansicht . Zum Beispiel zwischen einem 1- und 2-Spalten-Layout, wenn sich das Gerät dreht.
Das ist eine gängige und normale Redewendung in iOS. Leider kann dies nur durch die Lösung des in dieser Qualitätssicherung aufgeworfenen Problems erreicht werden. : - /
quelle
SpringDamping
undinitialSpringVelocity
) in Tabellenzelle ..... haben einen Blick auf diese Bouncy Liste mit Tableview ,,,, pastebin.com/pFRQhkrX Sie können die AnimationTableViewCell
in der Tabelle inwillDisplayCell:(UITableViewCell *)cell
delgate Methode @Fattie Sie annehmen können die Antwort, die Ihr Problem gelöst hat, um anderen zu helfen, die nach dem gleichen Problem suchenAntworten:
1. Lösung für iOS 13+
Mit Swift 5.1 und iOS 13 können Sie Compositional Layout-Objekte verwenden verwenden, um Ihr Problem zu lösen.
Der folgende vollständige Beispielcode zeigt, wie mehrzeilig
UILabel
in voller Breite angezeigt wirdUICollectionViewCell
:CollectionViewController.swift
HeaderView.swift
CustomCell.swift
Erwartete Anzeige:
2. Lösung für iOS 11+
Mit Swift 5.1 und iOS 11 können Sie eine Unterklasse
UICollectionViewFlowLayout
festlegen und derenestimatedItemSize
Eigenschaft auf festlegenUICollectionViewFlowLayout.automaticSize
(dies teilt dem System mit, dass Sie sich mit der automatischen Größenänderung befassen möchtenUICollectionViewCell
). Sie müssen dann überschreibenlayoutAttributesForElements(in:)
und die ZellenbreitelayoutAttributesForItem(at:)
einstellen. Zuletzt müssen Sie diepreferredLayoutAttributesFitting(_:)
Methode Ihrer Zelle überschreiben und ihre Höhe berechnen.Der folgende vollständige Code zeigt, wie mehrzeilig
UILabel
in voller Breite angezeigt wirdUIcollectionViewCell
(eingeschränkt durchUICollectionView
den sicheren Bereich undUICollectionViewFlowLayout
die Einfügungen):CollectionViewController.swift
CustomFlowLayout.swift
HeaderView.swift
CustomCell.swift
Hier sind einige alternative Implementierungen für
preferredLayoutAttributesFitting(_:)
:Erwartete Anzeige:
quelle
Problem
Sie suchen nach automatischer Höhe und möchten auch volle Breite haben, es ist nicht möglich, beide in Gebrauch zu bekommen
UICollectionViewFlowLayoutAutomaticSize
.Wenn Sie dies tun möchten,
UICollectionView
ist unten die Lösung für Sie.Lösung
1. Wenn Sie nur
UILabel
inCollectionViewCell
als die eingestelltenumberOfLines=0
und berechnet die erwartete HöheUIlable
, die alle drei paramters passieren2. Wenn Ihr
CollectionViewCell
nur enthältUIImageView
und wenn es in der Höhe dynamisch sein soll, dann müssen Sie die Höhe von erhaltenUIImage
(SieUIImageView
müssenAspectRatio
Einschränkungen haben)3. Wenn es beide enthält, berechnen Sie ihre Höhe und addieren Sie sie.
1. Fügen Sie
UICollectionViewDelegateFlowLayout
Ihrem viewController einen Delegaten hinzu2. Implementieren Sie die Delegate-Methode
Ich hoffe das hilft dir weiter.
quelle
return CGSize(width: view.frame.width/2, height: expectedHeight)
Behalten Sie auch die Auffüllung im Auge, als die Breite zurückzugeben, da sonst zwei Zellen nicht in eine einzelne Zeile passen würden.Es gibt verschiedene Möglichkeiten, dieses Problem anzugehen.
Eine Möglichkeit besteht darin, dem Ablauflayout der Sammlungsansicht eine geschätzte Größe zuzuweisen und die Zellengröße zu berechnen.
Hinweis: Wie in den Kommentaren unten erwähnt, müssen Sie ab iOS 10 keine geschätzte Größe mehr angeben, um den Aufruf einer Zelle auszulösen
func preferredLayoutAttributesFitting(_ layoutAttributes:)
. Zuvor (iOS 9) mussten Sie eine geschätzte Größe angeben, wenn Sie eine Zelle abfragen möchten. PrefferedLayoutAttributes.(Angenommen, Sie verwenden Storyboards und die Sammlungsansicht ist über IB verbunden.)
Für einfache Zellen reicht das normalerweise aus. Wenn die Größe immer noch falsch ist, können Sie sie in der Zelle der Sammlungsansicht überschreibenfunc preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes
, wodurch Sie die Zellengröße genauer steuern können. Hinweis: Sie müssen dem Flusslayout weiterhin eine geschätzte Größe geben .Überschreiben Sie dann
func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes
, um die richtige Größe zurückzugeben.Alternativ können Sie stattdessen eine Größenzelle verwenden, um die Größe der Zelle in der zu berechnen
UICollectionViewDelegateFlowLayout
.Dies sind zwar keine perfekten produktionsfertigen Beispiele, aber sie sollten Ihnen den richtigen Weg weisen. Ich kann nicht sagen, dass dies die beste Vorgehensweise ist, aber dies funktioniert für mich selbst bei ziemlich komplexen Zellen mit mehreren Beschriftungen, die möglicherweise in mehrere Zeilen eingeschlossen sind oder nicht.
quelle
preferredLayoutAttributesFitting
. Ich habe dann in dieser Funktion eine eigene Einschränkung hinzugefügt, die an die feste Dimension von EstimatedItemSize, FWIW, gebunden ist (siehe meine Antwort unten).Ich habe eine ziemlich einfache Lösung für dieses Problem gefunden: In meiner CollectionViewCell habe ich ein UIView (), das eigentlich nur ein Hintergrund ist. Um die volle Breite zu erhalten, habe ich einfach die folgenden Anker gesetzt
Die "Magie" geschieht in der ersten Zeile. Ich setze den widthAnchor dynamisch auf die Breite des Bildschirms. Wichtig ist auch, die Einfügungen Ihrer CollectionView zu subtrahieren. Andernfalls wird die Zelle nicht angezeigt. Wenn Sie keine solche Hintergrundansicht haben möchten, machen Sie sie einfach unsichtbar.
Das FlowLayout verwendet die folgenden Einstellungen
Das Ergebnis ist eine Zelle voller Größe mit dynamischer Höhe.
quelle
ARBEITEN!!! Getestet unter IOS: 12.1 Swift 4.1
Ich habe eine sehr einfache Lösung, die einfach ohne Einschränkungsbruch funktioniert.
Meine ViewControllerClass
CustomCell-Klasse:
Hauptbestandteil ist die systemLayoutSizeFitting Funktion in Customcell. Außerdem müssen wir die Breite der Ansicht in Cell mit Einschränkungen festlegen.
quelle
Sie müssen CollectionViewCell eine Breitenbeschränkung hinzufügen
quelle
Satz
estimatedItemSize
Ihres Ablauflayouts:Definieren Sie eine Breitenbeschränkung in der Zelle und stellen Sie sie so ein, dass sie der Breite der Übersicht entspricht:
Vollständiges Beispiel
Getestet auf iOS 11.
quelle
Persönlich habe ich die besten Möglichkeiten für eine UICollectionView gefunden, bei der AutoLayout die Größe bestimmt, während jede Zelle eine andere Größe haben kann, indem die Funktion UICollectionViewDelegateFlowLayout sizeForItemAtIndexPath implementiert wird, während eine tatsächliche Zelle zum Messen der Größe verwendet wird.
Ich habe darüber in einem meiner Blog-Beiträge gesprochen
Hoffentlich hilft Ihnen dieser, das zu erreichen, was Sie wollen. Ich bin nicht 100% sicher, aber ich glaube, im Gegensatz zu UITableView, wo Sie tatsächlich eine vollautomatische Höhe von Zellen haben können, indem Sie AutoLayout inkonjunktion mit verwenden
UICollectionView bietet AutoLayout nicht die Möglichkeit, die Größe zu bestimmen, da UICollectionViewCell nicht unbedingt die gesamte Bildschirmbreite ausfüllt.
Aber hier ist eine Frage für Sie : Wenn Sie Zellen mit voller Bildschirmbreite benötigen, warum verwenden Sie UICollectionView überhaupt gegenüber einer guten alten UITableView, die mit Zellen mit automatischer Größenanpassung geliefert wird?
quelle
Gemäß meinem Kommentar zu Erics Antwort ist meine Lösung seiner sehr ähnlich, aber ich musste eine Einschränkung in PreferredSizeFor ... hinzufügen, um mich auf die feste Dimension zu beschränken.
Diese Frage enthält eine Reihe von Duplikaten. Ich habe sie hier ausführlich beantwortet und hier eine funktionierende Beispiel-App bereitgestellt .
quelle
Ich bin mir nicht sicher, ob dies eine "wirklich gute Antwort" ist, aber ich verwende es, um dies zu erreichen. Mein Flusslayout ist horizontal und ich versuche, die Breite mit Autolayout anzupassen, sodass es Ihrer Situation ähnlich ist.
Dann starte ich im View Controller, in dem die Autolayout-Einschränkung geändert wird, eine NSNotification.
In meiner UICollectionView-Unterklasse warte ich auf diese Benachrichtigung:
und das Layout ungültig machen:
Dies führt
sizeForItemAt
dazu, dass die neue Größe der Sammlungsansicht erneut aufgerufen wird. In Ihrem Fall sollte es angesichts der neuen Einschränkungen im Layout aktualisiert werden können.quelle
Stellen Sie auf Ihrem
viewDidLayoutSubviews
dieestimatedItemSize
volle Breite ein (Layout bezieht sich auf das UICollectionViewFlowLayout-Objekt):Stellen Sie in Ihrer Zelle sicher, dass Ihre Einschränkungen sowohl den oberen als auch den unteren Rand der Zelle berühren (der folgende Code verwendet Kartografie, um das Festlegen der Einschränkungen zu vereinfachen, Sie können dies jedoch mit NSLayoutConstraint oder IB tun, wenn Sie möchten):
Voila, deine Zellen wachsen jetzt automatisch in der Höhe!
quelle
Keine der Lösungen funktionierte für mich, da ich eine dynamische Breite benötige, um mich zwischen der Breite des iPhones anzupassen.
quelle
Ab iOS 10 haben wir dafür eine neue API für das Flow-Layout.
Alles was Sie tun müssen, ist Ihre
flowLayout.estimatedItemSize
auf eine neue Konstante zu setzenUICollectionViewFlowLayoutAutomaticSize
.Quelle
quelle
AutoLayout kann zum automatischen Ändern der Größe von Zellen in CollectionView in zwei einfachen Schritten verwendet werden:
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
collectionView(:cellForItemAt:)
Erstellen Sie eine Containeransicht und legen Sie die Einschränkung containerView.widthAnchor.con von fest , um die Breite von contentView auf die Breite von collectionView zu beschränken.Das ist es, was Sie das gewünschte Ergebnis erhalten. Den vollständigen Code finden Sie in den folgenden Abschnitten:
Referenz / Credits:
Bildschirmfoto:
quelle
Sie müssen die Klasse UICollectionViewDelegateFlowLayout auf Ihrem collectionViewController erben. Fügen Sie dann die Funktion hinzu:
Damit haben Sie die Breite Größe der Bildschirmbreite.
Und Sie haben jetzt einen collectionViewController mit Zeilen als tableViewController.
Wenn die Größe der Höhe jeder Zelle dynamisch sein soll, sollten Sie möglicherweise benutzerdefinierte Zellen für jede benötigte Zelle erstellen.
quelle