Come centrare orizzontalmente le celle UICollectionView?


124

Ho svolto alcune ricerche, ma non sono riuscito a trovare alcun esempio di codice su come centrare le celle in un UICollectionView orizzontalmente.

invece che la prima cella sia come questa X00 , voglio che sia come questa 0X0 . c'è un modo per ottenere questo risultato?

MODIFICARE:

per visualizzare quello che voglio:

inserisci qui la descrizione dell'immagine

Ho bisogno che assomigli alla versione B quando è presente un solo elemento in CollectionView. Quando ho più di un elemento, dovrebbe essere come la versione A ma con più elementi.

Al momento sembra la versione A quando ho solo 1 elemento, e mi chiedo come posso farlo sembrare B.

Grazie per l'aiuto!


Non è più facile lasciare che la cella si adatti alla larghezza della vista della raccolta e quindi centrare la vista della raccolta stessa all'interno del suo genitore?
Arthur Gevorkyan

sì, ci sono almeno due modi per farlo, il primo (veloce) è rendere la larghezza della cella dell'intero schermo e centrare la sua visualizzazione figlio. il secondo (a destra) implementa il layout di visualizzazione della raccolta personalizzato
sage444

Alla fine ci saranno più celle provenienti dal backend, riempire l'intera larghezza non sarebbe una buona idea
RaptoX

aumentare la larghezza è sufficiente per impostare al centro
Kishore Kumar

Risposte:


228

Non è una buona idea usare una libreria, se il tuo scopo è solo questo, cioè allineare al centro.

Meglio puoi fare questo semplice calcolo nella tua funzione collectionViewLayout.

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. Grazie mille della risposta, ho implementato questo e le righe sono arrivate al centro come dovrebbero, ma ora il problema è che non riesco a scorrere fino al primo elemento. Quando provo a scorrere fino al primo elemento, mi riporta agli UIEdgeInsets modificati. Puoi vedere la mia app demo github.com/anirudha-music/CollectionViewCenter
Anirudha Mahale

5
In Swift 3, la nuova firma del metodo è collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int).
Kamchatka

1
come fai ad afferrare il cellWidth, è possibile tramite il metodo cellForItemAt? ho provato e non ha restituito nulla .. la larghezza della cella per me cambia in base alle dimensioni dello schermo .. @DarshanPatel.
Chris,

10
@DarshanPatel. La tua risposta a volte può produrre un valore negativo su dispositivi più piccoli. Considera di utilizzare un controllo massimo sul tuo leftInsetvalore in questo modo:let leftInset = max(0.0, (self.collectionView.bounds.width - CGFloat(totalCellWidth + totalSpacingWidth)) / 2)
Rhuari Glen

3
Se non stai creando una sottoclasse UICollectionViewController, assicurati che la tua classe sia conforme a UICollectionViewDelegateFlowLayout altrimenti non funzionerà
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)

    }

non dimenticare di aggiungere il protocollo

UICollectionViewDelegateFlowLayout

vincolo forse @ashForIos
Ahmed Safadi

La tua risposta funziona bene quando ci sono celle che si adattano alla collectionView quando il conteggio delle celle aumenta le celle sono al centro e non puoi scorrere fino alle prime celle o all'ultimo.
NickCoder

2
@Vitalii 80 larghezza media delle celle e 10 lo spazio tra le celle, se leggi il nome della variabile capiresti cosa significa: P
Ahmed Safadi

La soluzione Swift 4.2 è più semplice, GRAZIE! Assicurati solo di impostare "80" su qualunque sia la larghezza effettiva della cella-oggetto.
John Pitts,

25

Prova questo per 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)
    }

Aggiungi il tuo cellWidth invece di 165.0


1
questa è la migliore risposta. Con la matematica più semplice in esso. funziona con qualsiasi numero di righe e colonne
rickrvo

20

Uso KTCenterFlowLayout per questo e funziona alla grande. È una sottoclasse personalizzata UICollectionViewFlowLayoutche centra le celle come desideri. (Nota: questa non è una cosa banale da risolvere pubblicando del codice, motivo per cui mi sto collegando a un progetto GitHub!)


Impossibile farlo funzionare da IB. Questa libreria ha funzionato alla grande per me. Ho appena installato il pod e cambiato la classe di layout in IB!
tagirkaZ

15

Una versione obiettivo-C della risposta di Darshan Patel :

- (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;
}

Grazie. Funziona bene con fila singola. ma creando problemi su più righe. Non sono in grado di aggiungere l'URL qui per mostrare la schermata. . ma puoi aggiungere "yynoalzg" nel minuscolo URL. ti farai un'idea. La sezione Gold ha 4 record. Il quarto dovrebbe essere in una nuova riga. .ma dopo questo metodo viene visualizzato in questo modo ... fammi sapere se hai idea.
Hitarth

6

Modificando leggermente la risposta di @Safad Funy, questo è ciò che ha funzionato per me nella versione più recente di Swift e iOS. In questo caso, volevo che la larghezza delle celle fosse un terzo della dimensione della vista della raccolta.

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
Questo ha funzionato soprattutto per me, quando c'è solo una cella.
Dasoga

6

Puoi usare questa estensione (Swift 4).

Può centrare cellule con se collectionViewavetelayout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize .

Funziona con celle di qualsiasi dimensione e funziona perfettamente quando 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)
    }
}

Spero ti sia d'aiuto!


1
Errore di acquisizione: Thread 1: EXC_BAD_ACCESS (codice = 2, indirizzo = 0x118ffde58)
atulkhatri

4

Swift 4.2 (orizzontalmente e verticalmente). È un piccolo aggiornamento del codice Pink Panther e grazie mille!


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)

    }
}

Assicurati che la tua classe sia conforme al protocollo UICollectionViewDelegateFlowLayout


Davvero il tuo codice funziona alla grande per me, grazie Amico; )
steveSarsawa

4

Ecco la versione più recente di Swift 5 che funziona bene anche quando le celle sono più di una riga:

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
    }
}

Assicurati che la tua classe sia conforme al UICollectionViewDelegateFlowLayoutprotocollo.


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

Per le persone che vogliono solo aggiungere un'imbottitura (in alto, a sinistra, in basso, a destra ):

Aggiungi il protocollo UICollectionViewDelegateFlowLayout

Questo esempio mostra un'imbottitura sinistra e destra con 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

Puoi provare la mia soluzione, funziona bene,

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

La risposta accettata è la risposta giusta, ma se il tuo totalCellWidthè inferiore alla CollectionViews width, ma solo per evitare questo puoi fare come di seguito.

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

1

Questo codice dovrebbe centrare orizzontalmente la visualizzazione della raccolta anche in Swift 4.0 senza alcuna modifica:

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
    }
}

Assicurati che la tua classe sia conforme al UICollectionViewDelegateFlowLayoutprotocollo


0

Ho finito per adottare un approccio completamente diverso qui, che credo valga la pena menzionare.

Ho impostato un vincolo per l'allineamento orizzontale al centro della vista della raccolta. Quindi ho impostato un altro vincolo che specifica la larghezza. Ho creato una presa per il vincolo di larghezza all'interno del mio viewController che contiene la vista della raccolta. Quindi, quando la mia origine dati viene modificata e aggiorno la vista della raccolta, prendo il conteggio delle celle ed eseguo un calcolo (molto simile) per reimpostare la larghezza.

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

Quindi ho impostato le prese di vincolo .constant valore sul risultato del calcolo e il layout automatico fa il resto.

Ciò potrebbe essere in conflitto con `UICollectionViewDelegateFlowLayout, ma ha funzionato perfettamente per me per creare una vista della raccolta giustificata a sinistra. Senza un delegato, sembra funzionare solo quando le celle hanno riempito la maggior parte della visualizzazione.


0

Soluzione generale per il flowlayout che centra le pagine se sono inferiori alla larghezza e si allinea a sinistra se ce ne sono di più

- (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;
}

Versione Swift (convertita da 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
}

Untitled-3.png


Cosa sono i limiti nel codice swift?
Ricevo l'

Ciao, nel mio esempio ho implementato il metodo all'interno di un UIView, che ha limiti, se lo stai implementando altrove, usa i limiti appropriati
Peter Lapisu


0

il modo più semplice è impostare la dimensione della stima della vista della raccolta su Nessuno nello storyboard o con il codice layout.estimatedItemSize = CGSize.zero


0

Se c'è spazio solo per una cella per gruppo, a leading:e trailing:di .flexible(0)centreranno la cella orizzontalmente:

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

0

Ho usato quel codice in un progetto. Centra la collectionView orizzontalmente e verticalmente in entrambe le direzioni .horizontale .verticalutilizzando gli inserti della sezione. Rispetta la spaziatura e l'inserto originale della sezione se impostato. Codice da utilizzare nel delegato in UICollectionViewDelegateFlowLayoutmodo da avere accesso a tutte le proprietà di cui abbiamo bisogno per recuperare dal UIcollectionViewset o nello storyboard per la riusabilità.

// 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)
}

Spero che possa aiutare qualcuno: centra la sezione e non gli elementi all'interno della sezione, per di più dobbiamo sottoclassare UICollectionViewFlowLayouto UICollectionViewLayoutcome esempio di mosaico di Apple.


-4

Penso che sia necessario centrare la cella, quindi invece di usare collectionView, vorrei che UITableView sarà di grande utilità. Basta usare un UIViewController e posizionare due UIVview davanti e dietro e posizionarne una UITableViewnel mezzo. Spero che questo aiuti


Ho aggiunto una foto, per mostrarti di cosa ho esattamente bisogno, grazie!
RaptoX
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.