Wie zentriere ich UICollectionView-Zellen horizontal?


123

Ich habe einige Nachforschungen angestellt, aber ich konnte kein Codebeispiel zum horizontalen Zentrieren von Zellen in einer UICollectionView finden.

Anstatt dass die erste Zelle wie diese X00 ist , möchte ich, dass sie wie diese 0X0 ist . Gibt es eine Möglichkeit, dies zu erreichen?

BEARBEITEN:

um zu visualisieren, was ich will:

Geben Sie hier die Bildbeschreibung ein

Ich brauche es, um wie Version B auszusehen, wenn es nur ein Element in der CollectionView gibt. Wenn ich mehr als ein Element habe, sollte es wie Version A sein, aber mit mehr Elementen.

Im Moment sieht es aus wie Version A, wenn ich nur 1 Element habe, und ich frage mich, wie ich es so aussehen lassen kann wie B.

Danke für die Hilfe!


Ist es nicht einfacher, die Zelle an die Breite der Sammlungsansicht anzupassen und dann die Sammlungsansicht selbst in ihrem übergeordneten Element zu zentrieren?
Arthur Gevorkyan

Ja, es gibt mindestens zwei Möglichkeiten, dies zu tun: Erstens (schnell) besteht die Zellbreite des gesamten Bildschirms und die Zentrierung der untergeordneten Ansicht. zweite (rechts) implementieren benutzerdefinierte Sammlung Ansicht Layout
sage444

Es werden irgendwann mehr Zellen aus dem Backend kommen, die gesamte Breite
auszufüllen

Erhöhen Sie die Breite ist genug, um in der Mitte zu setzen
Kishore Kumar

Antworten:


227

Es ist keine gute Idee, eine Bibliothek zu verwenden, wenn Ihr Zweck nur darin besteht, die Ausrichtung zu zentrieren.

Besser können Sie diese einfache Berechnung in Ihrer collectionViewLayout-Funktion durchführen.

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {

    let totalCellWidth = CellWidth * CellCount
    let totalSpacingWidth = CellSpacing * (CellCount - 1)

    let leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset

    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}

2
@ DarshanPatel. Vielen Dank für die Antwort, die ich implementiert habe, und die Zeilen kamen in die Mitte, wie es sollte, aber jetzt ist das Problem, dass ich nicht zum ersten Element scrollen kann. Wenn ich versuche, zum ersten Element zu scrollen, kehre ich zu den geänderten UIEdgeInsets zurück. Sie können meine Demo-App github.com/anirudha-music/CollectionViewCenter
Anirudha Mahale

5
In Swift 3 lautet die neue Methodensignatur collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int).
Kamtschatka

1
Wie können Sie die Zellenbreite erfassen? Ist dies über die Methode cellForItemAt möglich? Ich habe es versucht und es hat null zurückgegeben. Die Zellenbreite ändert sich für mich basierend auf der Bildschirmgröße. @DarshanPatel.
Chris

10
@DarshanPatel. Ihre Antwort kann bei kleineren Geräten manchmal zu einem negativen Wert führen. leftInsetlet leftInset = max(0.0, (self.collectionView.bounds.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2)
Erwägen

3
Wenn Sie UICollectionViewController nicht unterklassifizieren, stellen Sie sicher, dass Ihre Klasse UICollectionViewDelegateFlowLayout entspricht, da dies sonst nicht funktioniert
Saeed Ir

59

Swift 5.1

func centerItemsInCollectionView(cellWidth: Double, numberOfItems: Double, spaceBetweenCell: Double, collectionView: UICollectionView) -> UIEdgeInsets {
    let totalWidth = cellWidth * numberOfItems
    let totalSpacingWidth = spaceBetweenCell * (numberOfItems - 1)
    let leftInset = (collectionView.frame.width - CGFloat(totalWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset
    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}

Swift 4.2

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

    let totalCellWidth = 80 * collectionView.numberOfItems(inSection: 0)
    let totalSpacingWidth = 10 * (collectionView.numberOfItems(inSection: 0) - 1)

    let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
    let rightInset = leftInset

    return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)

}

Swift 3

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {

        let totalCellWidth = 80 * collectionView.numberOfItems(inSection: 0)
        let totalSpacingWidth = 10 * (collectionView.numberOfItems(inSection: 0) - 1)

        let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
        let rightInset = leftInset

        return UIEdgeInsetsMake(0, leftInset, 0, rightInset)

    }

Vergessen Sie nicht, das Protokoll hinzuzufügen

UICollectionViewDelegateFlowLayout

Einschränkung vielleicht @ashForIos
Ahmed Safadi

Ihre Antwort funktioniert einwandfrei, wenn Zellen in collectionView passen, wenn die Zellenzahl zunimmt. Die Zellen sind zentriert und Sie können nicht zu den ersten oder letzten Zellen scrollen.
NickCoder

2
@Vitalii 80 bedeutet Zellenbreite und 10 den Abstand zwischen den Zellen. Wenn Sie den Variablennamen lesen, werden Sie verstehen, was er bedeutet: P
Ahmed Safadi

Die Swift 4.2-Lösung ist einfacher, DANKE! Stellen Sie einfach sicher, dass "80" auf die tatsächliche Breite Ihres Zellenobjekts eingestellt ist.
John Pitts

25

Versuchen Sie dies für Swift 4

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let cellWidth : CGFloat = 165.0

        let numberOfCells = floor(self.view.frame.size.width / cellWidth)
        let edgeInsets = (self.view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsetsMake(15, edgeInsets, 0, edgeInsets)
    }

Fügen Sie stattdessen Ihre cellWidth 165.0 hinzu


1
Das ist die beste Antwort. Mit der einfachsten Mathematik. arbeitet mit einer beliebigen Anzahl von Zeilen und Spalten
Rickrvo

20

Ich benutze dafür KTCenterFlowLayout und es funktioniert großartig. Es ist eine benutzerdefinierte Unterklasse UICollectionViewFlowLayout, die Zellen nach Ihren Wünschen zentriert. (Hinweis: Dies ist keine triviale Sache, die durch das Posten von Code gelöst werden muss. Deshalb verlinke ich auf ein GitHub-Projekt!)


Konnte nicht von IB funktionieren. Diese Bibliothek hat für mich wie ein Zauber gewirkt. Einfach den Pod installiert und die Layoutklasse in IB geändert!
tagirkaZ

15

Eine objektive C-Version von Darshan Patels Antwort :

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    CGFloat totalCellWidth = kItemWidth * self.dataArray.count;
    CGFloat totalSpacingWidth = kSpacing * (((float)self.dataArray.count - 1) < 0 ? 0 :self.dataArray.count - 1);
    CGFloat leftInset = (self.bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2;
    CGFloat rightInset = leftInset;
    UIEdgeInsets sectionInset = UIEdgeInsetsMake(0, leftInset, 0, rightInset);
    return sectionInset;
}

Vielen Dank. Es funktioniert gut mit einer Reihe. aber Problem in mehreren Zeilen erstellen. Ich bin nicht in der Lage, URL hier hinzuzufügen, um u Screenshot zu zeigen. . Sie können jedoch "yynoalzg" in einer winzigen URL hinzufügen. Du wirst eine Idee bekommen. Gold Abschnitt haben 4 Rekord. 4. sollte in neuer Zeile sein. Aber nach dieser Methode wird es so angezeigt ... lassen Sie mich wissen, wenn Sie eine Idee haben.
Hitarth

6

Die Antwort von @Safad Funy leicht modifiziert, hat in der neuesten Version von Swift & iOS für mich funktioniert. In diesem Fall wollte ich, dass die Breite der Zellen ein Drittel der Größe der Sammlungsansicht beträgt.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

  let totalCellWidth = Int(collectionView.layer.frame.size.width) / 3 * collectionView.numberOfItems(inSection: 0)
  let totalSpacingWidth = (collectionView.numberOfItems(inSection: 0) - 1)

  let leftInset = (collectionView.layer.frame.size.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
  let rightInset = leftInset

  return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}

2
Dies hat bei mir besonders funktioniert, wenn es nur eine Zelle gibt.
Dasoga

6

Sie können diese Erweiterung verwenden (Swift 4).

Es kann Zellen mit zentrieren, wenn Sie collectionViewhaben layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize.

Es funktioniert mit jeder Zellengröße und funktioniert perfekt, wenn scrollDirection = .horizontal

public extension UICollectionView {
    func centerContentHorizontalyByInsetIfNeeded(minimumInset: UIEdgeInsets) {
        guard let layout = collectionViewLayout as? UICollectionViewFlowLayout,
            layout.scrollDirection == .horizontal else {
                assertionFailure("\(#function): layout.scrollDirection != .horizontal")
                return
        }

        if layout.collectionViewContentSize.width > frame.size.width {
            contentInset = minimumInset
        } else {
            contentInset = UIEdgeInsets(top: minimumInset.top,
                                        left: (frame.size.width - layout.collectionViewContentSize.width) / 2,
                                        bottom: minimumInset.bottom,
                                        right: 0)
        }
    }
}


final class Foo: UIViewController {
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        collectionView.centerContentHorizontalyByInsetIfNeeded(minimumInset: yourDefaultInset)
    }
}

Hoffe es hilft dir!


1
Fehler erhalten: Thread 1: EXC_BAD_ACCESS (Code = 2, Adresse = 0x118ffde58)
Atulkhatri

4

Swift 4.2 (horizontal und vertikal). Es ist ein kleines Upgrade des Pink Panther-Codes und ein großes Dankeschön an ihn!


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellHieght: CGFloat = flowLayout.itemSize.height
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    var collectionHeight = collectionView.frame.size.height
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
        collectionHeight -= collectionView.safeAreaInsets.top + collectionView.safeAreaInsets.bottom
    }
    let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
    let totalHieght = cellHieght * cellCount + cellSpacing * (cellCount - 1)
    if totalWidth <= collectionWidth {
        let edgeInsetWidth = (collectionWidth - totalWidth) / 2

        print(edgeInsetWidth, edgeInsetWidth)
        return UIEdgeInsets(top: 5, left: edgeInsetWidth, bottom: flowLayout.sectionInset.top, right: edgeInsetWidth)
    } else {
        let edgeInsetHieght = (collectionHeight - totalHieght) / 2
        print(edgeInsetHieght, edgeInsetHieght)
        return UIEdgeInsets(top: edgeInsetHieght, left: flowLayout.sectionInset.top, bottom: edgeInsetHieght, right: flowLayout.sectionInset.top)

    }
}

Stellen Sie sicher, dass Ihre Klasse dem UICollectionViewDelegateFlowLayout- Protokoll entspricht


Wirklich, dein Code funktioniert großartig für mich, danke, Alter. )
SteveSarsawa

4

Hier ist die neuere Version für Swift 5, die auch funktioniert, wenn die Zellen mehr als eine Zeile umfassen:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    var cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    var totalWidth: CGFloat
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
    }
    repeat {
        totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
        cellCount -= 1
    } while totalWidth >= collectionWidth

    if (totalWidth > 0) {
        let edgeInset = (collectionWidth - totalWidth) / 2
        return UIEdgeInsets.init(top: flowLayout.sectionInset.top, left: edgeInset, bottom: flowLayout.sectionInset.bottom, right: edgeInset)
    } else {
        return flowLayout.sectionInset
    }
}

Bitte stellen Sie sicher, dass Ihre Klasse dem Protokoll entsprichtUICollectionViewDelegateFlowLayout .


3

Swift 4

extension ViewController: UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

        let cellWidth: CGFloat = 170.0 // Your cell width

        let numberOfCells = floor(view.frame.size.width / cellWidth)
        let edgeInsets = (view.frame.size.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsetsMake(0, edgeInsets, 0, edgeInsets)
    }

 }

2

Für die Personen, die nur eine Polsterung hinzufügen möchten ( oben, links, unten, rechts ):

Fügen Sie das Protokoll hinzu UICollectionViewDelegateFlowLayout

Dieses Beispiel zeigt eine Polsterung links und rechts mit 40.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {        
    return UIEdgeInsetsMake(0, 40, 0, 40)
}

2

SWIFT 4.2

private lazy var contentView: UICollectionView = {
        let layoutView: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            layoutView.scrollDirection = .horizontal
            layoutView.minimumInteritemSpacing = 0
            layoutView.minimumLineSpacing = 5

        let collectionView: UICollectionView = UICollectionView(frame: .zero, collectionViewLayout: layoutView)
            collectionView.dataSource = self
            collectionView.delegate = self
            collectionView.showsHorizontalScrollIndicator = false
            collectionView.isPagingEnabled = true
            collectionView.registerCell(Cell.self)
            collectionView.backgroundColor = .clear
            collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()

// //

extension CustomCollectionView: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        return CGSize(width: collectionView.frame.width*4/5, height: collectionView.frame.height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        let cellWidth : CGFloat = collectionView.frame.width*4/5

        let numberOfCells = floor(collectionView.frame.width / cellWidth)
        let edgeInsets = (collectionView.frame.width - (numberOfCells * cellWidth)) / (numberOfCells + 1)

        return UIEdgeInsets(top: 0, left: edgeInsets, bottom: 0, right: edgeInsets)
    }
}

1

Sie können meine Lösung ausprobieren, es funktioniert gut,

func refreshCollectionView(_ count: Int) {
    let collectionViewHeight = collectionView.bounds.height
    let collectionViewWidth = collectionView.bounds.width
    let numberOfItemsThatCanInCollectionView = Int(collectionViewWidth / collectionViewHeight)
    if numberOfItemsThatCanInCollectionView > count {
        let totalCellWidth = collectionViewHeight * CGFloat(count)
        let totalSpacingWidth: CGFloat = CGFloat(count) * (CGFloat(count) - 1)
        // leftInset, rightInset are the global variables which I am passing to the below function
        leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2;
        rightInset = -leftInset
    } else {
        leftInset = 0.0
        rightInset = -collectionViewHeight
    }
    collectionView.reloadData()
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
}

1

Die akzeptierte Antwort ist die richtige Antwort, aber wenn Sie totalCellWidthkleiner als die ist CollectionView, widthkönnen Sie wie folgt vorgehen , um sich dagegen zu schützen.

if (leftInset > 0) {
     return UIEdgeInsetsMake(0, leftInset, 0, rightInset)
  } else {
     return UIEdgeInsetsMake(0, 10, 0, 10)
}

1

Dieser Code sollte die Sammlungsansicht auch in Swift 4.0 ohne Änderung horizontal zentrieren:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    let cellWidth: CGFloat = flowLayout.itemSize.width
    let cellSpacing: CGFloat = flowLayout.minimumInteritemSpacing
    let cellCount = CGFloat(collectionView.numberOfItems(inSection: section))
    var collectionWidth = collectionView.frame.size.width
    if #available(iOS 11.0, *) {
        collectionWidth -= collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right
    }
    let totalWidth = cellWidth * cellCount + cellSpacing * (cellCount - 1)
    if totalWidth <= collectionWidth {
        let edgeInset = (collectionWidth - totalWidth) / 2
        return UIEdgeInsetsMake(flowLayout.sectionInset.top, edgeInset, flowLayout.sectionInset.bottom, edgeInset)
    } else {
        return flowLayout.sectionInset
    }
}

Stellen Sie sicher, dass Ihre Klasse dem UICollectionViewDelegateFlowLayoutProtokoll entspricht


0

Am Ende habe ich hier einen völlig anderen Ansatz gewählt, der meiner Meinung nach erwähnenswert ist.

Ich habe eine Einschränkung für meine Sammlungsansicht festgelegt, die horizontal in der Mitte ausgerichtet ist. Dann habe ich eine weitere Einschränkung festgelegt, die die Breite angibt. Ich habe in meinem viewController einen Ausgang für die Breitenbeschränkung erstellt, der die Sammlungsansicht enthält. Wenn dann meine Datenquelle geändert wird und ich die Sammlungsansicht aktualisiere, nehme ich die Anzahl der Zellen und führe eine (sehr ähnliche) Berechnung durch, um die Breite zurückzusetzen.

let newWidth = (items.count * cellWidth) + (items.count * cellSpacing)

Dann setze ich den .constantWert des Constraint Outlets auf das Berechnungsergebnis und Autolayout erledigt den Rest.

Dies kann zu Konflikten mit dem UICollectionViewDelegateFlowLayout führen, aber dies hat perfekt funktioniert, um eine linksbündige Sammlungsansicht zu erstellen. Ohne einen Delegierten scheint es nur zu funktionieren, wenn die Zellen den größten Teil der Ansicht ausfüllen.


0

Allgemeine Lösung für das Flowlayout, bei dem die Seiten zentriert werden, wenn sie kleiner als die Breite sind, und links ausgerichtet werden, wenn mehr vorhanden sind

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    // Centering if there are fever pages
    CGSize itemSize = [(UICollectionViewFlowLayout *)collectionViewLayout itemSize];
    CGFloat spacing = [(UICollectionViewFlowLayout *)collectionViewLayout minimumLineSpacing];

    NSInteger count = [self collectionView:self numberOfItemsInSection:section];
    CGFloat totalCellWidth = itemSize.width * count;
    CGFloat totalSpacingWidth = spacing * ((count - 1) < 0 ? 0 : count - 1);
    CGFloat leftInset = (self.bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2;
    if (leftInset < 0) {
        UIEdgeInsets inset = [(UICollectionViewFlowLayout *)collectionViewLayout sectionInset];
        return inset;
    }
    CGFloat rightInset = leftInset;
    UIEdgeInsets sectionInset = UIEdgeInsetsMake(0, leftInset, 0, rightInset);
    return sectionInset;
}

Schnelle Version (konvertiert von ObjC)

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    // Centering if there are fever pages
    let itemSize: CGSize? = (collectionViewLayout as? UICollectionViewFlowLayout)?.itemSize
    let spacing: CGFloat? = (collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing

    let count: Int = self.collectionView(self, numberOfItemsInSection: section)
    let totalCellWidth = (itemSize?.width ?? 0.0) * CGFloat(count)
    let totalSpacingWidth = (spacing ?? 0.0) * CGFloat(((count - 1) < 0 ? 0 : count - 1))
    let leftInset: CGFloat = (bounds.size.width - (totalCellWidth + totalSpacingWidth)) / 2
    if leftInset < 0 {
        let inset: UIEdgeInsets? = (collectionViewLayout as? UICollectionViewFlowLayout)?.sectionInset
        return inset!
    }
    let rightInset: CGFloat = leftInset
    let sectionInset = UIEdgeInsets(top: 0, left: Float(leftInset), bottom: 0, right: Float(rightInset))
    return sectionInset
}

Ohne Titel-3.png


Was sind Grenzen im schnellen Code? Ich
erhalte

Hallo, in meinem Beispiel habe ich die Methode in einem UIView implementiert, das Grenzen hat. Wenn Sie sie an anderer Stelle implementieren, verwenden Sie die entsprechenden Grenzen
Peter Lapisu


0

Am einfachsten ist es, die geschätzte Größe der Sammlungsansicht im Storyboard oder mit Code auf Keine zu setzen layout.estimatedItemSize = CGSize.zero


0

Wenn nur Platz für eine Zelle pro Gruppe vorhanden ist, zentriert ein leading:und trailing:von .flexible(0)die Zelle horizontal:

item.edgeSpacing = NSCollectionLayoutEdgeSpacing(
    leading: .flexible(0), top: nil,                                                     
    trailing: .flexible(0), bottom: nil
)

0

Ich habe diesen Code in einem Projekt verwendet. Es zentriert die collectionView horizontal und vertikal in beide Richtungen .horizontalund unter .verticalVerwendung der Einfügungen des Abschnitts. Respektiert den Abstand und den ursprünglichen Einschub des Abschnitts, falls festgelegt. Code, der im Delegaten verwendet werden soll, UICollectionViewDelegateFlowLayoutdamit wir Zugriff auf alle Eigenschaften haben, die wir UIcollectionViewzur Wiederverwendbarkeit aus dem Storyboard abrufen oder im Storyboard festlegen müssen.

// original function of the delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    // casting the layout as a UICollectionViewFlowLayout to have access to the properties of items for reusability - you could also link the real one from the storyboard with an outlet
    let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
    // getting all the properties we need
    let itemWidth = flowLayout.itemSize.width
    let itemHeight = flowLayout.itemSize.height
    let interSpacing = flowLayout.minimumInteritemSpacing
    let lineSpacing = flowLayout.minimumLineSpacing
    // getting the size of the collectionView
    let collectionWidth = collectionView.bounds.width
    let collectionHeight = collectionView.bounds.height
    // getting the direction to choose how to align the collection
    let direction = flowLayout.scrollDirection
    // you don't want to have an item greater than the collection
    guard (itemWidth < collectionWidth && direction == .vertical) || (itemHeight < collectionHeight && direction == .horizontal) else {
        print("Really?")
        return UIEdgeInsets(top: flowLayout.sectionInset.top, left: flowLayout.sectionInset.left, bottom: flowLayout.sectionInset.bottom, right: flowLayout.sectionInset.right)
    }
    // getting the number of item in the current section
    let totalItemCount = CGFloat(collectionView.numberOfItems(inSection: section))
    // setting number of item in a row to the max number of items that can fit in a row without spacing or to the number of items in the section if less than the max
    var itemCountInRow = totalItemCount < (collectionWidth / itemWidth).rounded(.towardZero) ? totalItemCount : (collectionWidth / itemWidth).rounded(.towardZero)
    // how many max row can we have
    var countOfRow = totalItemCount < (collectionHeight / itemHeight).rounded(.towardZero) ? totalItemCount : (collectionHeight / itemHeight).rounded(.towardZero)
    // calculating the total width of row by multiplying the number of items in the row by the width of item and adding the spacing multiplied by the number of item minus one
    var totalWidthOfRow:CGFloat {
        get{
            return (itemWidth * itemCountInRow) + (interSpacing * (itemCountInRow - 1))
        }
    }
    // calculating the total height of row by multiplying the number of row by the height of item and adding the spacing multiplied by the number of row minus one
    var totalHeightOfRow:CGFloat {
        get{
            return (itemHeight * countOfRow) + (lineSpacing * (countOfRow - 1))
        }
    }
    // first we set the inset to the default
    var edgeInsetLeft = flowLayout.sectionInset.left
    var edgeInsetTop = flowLayout.sectionInset.top

    if direction == .vertical {
        // while the width of row with original margin is greater than the width of the collection we drop one item until it fits
        while totalWidthOfRow > collectionWidth || ((collectionWidth - totalWidthOfRow) / 2) < flowLayout.sectionInset.left {
            // droping an item to fit in the row
            itemCountInRow -= 1
        }
        // calculating the number of rows in collectionView by dividing the number of items by the number of items in a row
        countOfRow = (totalItemCount / (itemCountInRow)).rounded(.up)
    } else {
        itemCountInRow = (totalItemCount / countOfRow).rounded(.up)
        // while the height of row with original marginis greater than the height of the collection we drop one row until it fits
        while totalHeightOfRow >= collectionHeight  || ((collectionHeight - totalHeightOfRow) / 2) < flowLayout.sectionInset.top  {
            // droping an item to fit in the row
            countOfRow -= 1
        }
    }
    edgeInsetLeft = max(flowLayout.sectionInset.left, (collectionWidth - totalWidthOfRow) / 2)
    edgeInsetTop = max(flowLayout.sectionInset.top, (collectionHeight - totalHeightOfRow) / 2)
    // we don't specially need insets where the items are overflowing
    let edgeInsetRight = direction == .vertical ? edgeInsetLeft : flowLayout.sectionInset.right
    let edgeInsetBottom = direction == .horizontal ? edgeInsetTop : flowLayout.sectionInset.bottom
    // returning the UIEdgeInsets
    return UIEdgeInsets(top: edgeInsetTop, left: edgeInsetLeft, bottom: edgeInsetBottom, right: edgeInsetRight)
}

Hoffe, es würde jemandem helfen - es zentriert den Abschnitt, nicht die Elemente innerhalb des Abschnitts, für mehr müssen wir das UICollectionViewFlowLayoutoder UICollectionViewLayoutals Mosaikbeispiel von Apple unterordnen.


-3

Ich denke, Sie müssen die Zelle zentrieren, also wird UITableView anstelle von collectionView von großem Nutzen sein. Verwenden Sie einfach einen UIViewController und platzieren Sie zwei UIViews vorne und hinten und platzieren Sie eine UITableViewmittlere Hoffnung. Dies hilft


Ich habe ein Bild hinzugefügt, um Ihnen zu zeigen, was genau ich brauche, danke!
RaptoX
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.