UICollectionView margini di spaziatura


181

Ho un UICollectionViewche mostra le foto. Ho creato la raccolta visualizzazioni utilizzando UICollectionViewFlowLayout. Funziona bene, ma vorrei avere una spaziatura sui margini. È possibile farlo utilizzando UICollectionViewFlowLayouto devo implementare il mio UICollectionViewLayout?

Risposte:


333

È possibile utilizzare il collectionView:layout:insetForSectionAtIndex:metodo per il proprio UICollectionViewo impostare la sectionInsetproprietà UICollectionViewFlowLayoutdell'oggetto allegato al proprio UICollectionView:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsMake(top, left, bottom, right);
}

o

UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[aFlowLayout setSectionInset:UIEdgeInsetsMake(top, left, bottom, right)];

Aggiornato per Swift 5

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
       return UIEdgeInsets(top: 25, left: 15, bottom: 0, right: 5)
    }

35
Non sembra che le inserzioni sinistra e destra funzionino quando si utilizza un layout a flusso verticale ...
John

1
Ora anche l'override del metodo sectionInset di UICollectionViewFlowLayout sottoclassato non ha alcun effetto. L'impostazione della proprietà descritta di seguito funziona.
Dren,

4
NB: ricordati di aggiungere UICollectionViewDelegateFlowLayoutal tuo elenco di delegati ViewController per utilizzare il metodoinsetForSectionAtIndex
David Douglas

98

Impostazione di inserti in Interface Builder come mostrato nella schermata qui sotto

Impostazione degli inserti di sezione per UICollectionView

Si tradurrà in qualcosa del genere:

Una cella di visualizzazione raccolta con inserti di sezione


2
Ottima risposta, volevo solo sottolineare che dovrai anche giocare con la spaziatura minima in modo che l'inserzione della sezione funzioni bene.
Smit Yash,

75

Per aggiungere la spaziatura sull'intero UICollectionView :

UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) collection.collectionViewLayout;
flow.sectionInset = UIEdgeInsetsMake(topMargin, left, bottom, right);

Per giocare con la spaziatura tra gli elementi della stessa riga (colonna se stai scorrendo in senso orizzontale) e le loro dimensioni:

flow.itemSize = ...;
flow.minimumInteritemSpacing = ...;

5
Funziona, ma collection.collectionViewLayoutnecessita di un cast come nell'esempio di @Pooja: UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) self.collectionViewLayout;
jwj

Casting in rapidif let flow = collectionViewLayout as? UICollectionViewFlowLayout { flow.itemSize = CGSize(width: 100, height: 100) }
emily

41

Swift 4

    let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout // If you create collectionView programmatically then just create this flow by UICollectionViewFlowLayout() and init a collectionView by this flow.

    let itemSpacing: CGFloat = 3
    let itemsInOneLine: CGFloat = 3
    flow.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    let width = UIScreen.main.bounds.size.width - itemSpacing * CGFloat(itemsInOneLine - 1) //collectionView.frame.width is the same as  UIScreen.main.bounds.size.width here.
    flow.itemSize = CGSize(width: floor(width/itemsInOneLine), height: width/itemsInOneLine)
    flow.minimumInteritemSpacing = 3
    flow.minimumLineSpacing = 3

MODIFICA XCodice 11.4 e rapido 5

let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

non funziona Usa sotto le opere.

let flow = UICollectionViewFlowLayout()

inserisci qui la descrizione dell'immagine


C'è un modo per impostare il colore alla spaziatura?
Martín Serrano,

1
@ MartínDaniel Ho appena impostato backgroundColoril collectionView. O qualunque sia la super vista.
William Hu,

1
ma non ci sono margini ai bordi
user924

@ user924 I margini ai bordi possono essere impostati con UIEdgeInsets (in alto: a sinistra: in basso: a destra:). Se si scorre verticalmente, impostare gli inserti sinistro / destro. Se si scorre in orizzontale, impostare gli inserti superiore e inferiore.
Marcy,

40

Giusto per correggere alcune informazioni errate in questa pagina:

1- minimumInteritemSpacing : la spaziatura minima da utilizzare tra gli elementi nella stessa riga.

Il valore predefinito: 10.0.

(Per una griglia a scorrimento verticale, questo valore rappresenta la spaziatura minima tra gli elementi nella stessa riga.)

2- minimumLineSpacing : la spaziatura minima da utilizzare tra le righe degli elementi nella griglia.

Rif: http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewFlowLayout_class/Reference/Reference.html


2
Ciò non sembra influire sulla spaziatura tra le sezioni, ma solo tra gli elementi all'interno della stessa sezione?
Crashalot,

@Crashalot - sei sicuro di non voler intendere minimoLineSpacing? cioè ogni linea di cellule? Ci sono anche opzioni per gli inserti di sezione se stai davvero usando le sezioni.
Chucky,

Questo ha funzionato per me facendolo tramite l'interfaccia dello storyboard. Stavo cercando una soluzione per le viste di raccolta solo orizzontali. Grazie +10
kemicofa ghost

9

Moderno, rapido, calcolo automatico del layout

Mentre questa discussione contiene già un sacco di risposte utili, voglio aggiungere una versione Swift moderna , basata sulla risposta di William Hu. Migliora anche due cose:

  • La spaziatura tra linee diverse ora corrisponderà sempre alla spaziatura tra elementi nella stessa riga.
  • Impostando una larghezza minima, il codice calcola automaticamente il numero di elementi in una riga e applica quello stile al layout del flusso.

Ecco il codice:

// Create flow layout
let flow = UICollectionViewFlowLayout()

// Define layout constants
let itemSpacing: CGFloat = 1
let minimumCellWidth: CGFloat = 120
let collectionViewWidth = collectionView!.bounds.size.width

// Calculate other required constants
let itemsInOneLine = CGFloat(Int((collectionViewWidth - CGFloat(Int(collectionViewWidth / minimumCellWidth) - 1) * itemSpacing) / minimumCellWidth))
let width = collectionViewWidth - itemSpacing * (itemsInOneLine - 1)
let cellWidth = floor(width / itemsInOneLine)
let realItemSpacing = itemSpacing + (width / itemsInOneLine - cellWidth) * itemsInOneLine / max(1, itemsInOneLine - 1))

// Apply values
flow.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
flow.itemSize = CGSize(width: cellWidth, height: cellWidth)
flow.minimumInteritemSpacing = realItemSpacing
flow.minimumLineSpacing = realItemSpacing

// Apply flow layout
collectionView?.setCollectionViewLayout(flow, animated: false)

Se itemsInOneLineè 1, ciò comporterà un NaN a causa della divisione per zero qui:itemsInOneLine / (itemsInOneLine - 1)
TylerJames,

1
@TylerJames Grazie! Ho modificato il codice per risolvere il problema;)
fredpi

8

utilizzare setMinimumLineSpacing:e setMinimumInteritemSpacing:sulla UICollectionViewFlowLayout-Oggetto.


No, non funziona, come previsto. setMinimumLineSpacing è: la spaziatura minima da utilizzare tra gli elementi nella stessa riga. E setMinimumInteritemSpacing è: la spaziatura minima da utilizzare tra le linee di elementi nella griglia. La mia domanda riguarda i margini e non lo spazio tra gli elementi. per esempio. Spaziatura sinistra e superiore del primo elemento.
Mert

assumendo una direzione verticale, puoi usare contentInset per la spaziatura superiore e inferiore della prima e dell'ultima riga. Inoltre potresti aggiungere i tuoi margini nelle tue celle.
Jonathan Cichon,

8

Usando collectionViewFlowLayout.sectionInseto collectionView:layout:insetForSectionAtIndex:sono corretti.

Tuttavia, se collectionView ha più sezioni e si desidera aggiungere margine all'intera collectionView, si consiglia di utilizzare scrollView contentInset:

UIEdgeInsets collectionViewInsets = UIEdgeInsetsMake(50.0, 0.0, 30.0, 0.0);
self.collectionView.contentInset = collectionViewInsets;
self.collectionView.scrollIndicatorInsets = UIEdgeInsetsMake(collectionViewInsets.top, 0, collectionViewInsets.bottom, 0);

5

Per mettere spazio tra i CollectionItems usa questo

scrivi queste due righe in viewdidload

UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
collectionViewLayout.sectionInset = UIEdgeInsetsMake(<CGFloat top>, <CGFloat left>, <CGFloat bottom>, <CGFloat right>)

5

Imposta la insetForSectionAtproprietà UICollectionViewFlowLayoutdell'oggetto collegato al tuoUICollectionView

Assicurati di aggiungere questo protocollo

UICollectionViewDelegateFlowLayout

veloce

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets (top: top, left: left, bottom: bottom, right: right)
    }

Obiettivo - C

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsMake(top, left, bottom, right);
}

2

In Objective-C

CGFloat spacing = 5;
UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*)_habbitCollectionV.collectionViewLayout;
flow.sectionInset = UIEdgeInsetsMake(0, spacing, 0, spacing);
CGFloat itemsPerRow = 2;
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat oneMore = itemsPerRow + 1;
CGFloat width = screenRect.size.width - spacing * oneMore;
CGFloat height = width / itemsPerRow;

flow.itemSize = CGSizeMake(floor(height), height);
flow.minimumInteritemSpacing = spacing;
flow.minimumLineSpacing = spacing;

Tutto quello che devi fare è cambiare il valore itemsPerRow e aggiornerà di conseguenza il numero di elementi per riga. Inoltre, puoi modificare il valore della spaziatura se desideri una spaziatura più o meno generale.

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine


1
Bello ... è perfetto.
sohil,

1

Per aggiungere margini alle celle specificate, è possibile utilizzare questo layout di flusso personalizzato. https://github.com/voyages-sncf-technologies/VSCollectionViewCellInsetFlowLayout/

extension ViewController : VSCollectionViewDelegateCellInsetFlowLayout 
{
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemAt indexPath: IndexPath) -> UIEdgeInsets {
        if indexPath.item == 0 {
            return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
        }
        return UIEdgeInsets.zero
    }
}

0

In swift 4 e autoLayout, puoi usare sectionInset in questo modo:

let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        layout.itemSize = CGSize(width: (view.frame.width-40)/2, height: (view.frame.width40)/2) // item size
        layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10) // here you can add space to 4 side of item
        collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout) // set layout to item
        collectionView?.register(ProductCategoryCell.self, forCellWithReuseIdentifier: cellIdentifier) // registerCell
        collectionView?.backgroundColor = .white // background color of UICollectionView
        view.addSubview(collectionView!) // add UICollectionView to view

-1

Per aggiungere una separazione di 10px tra ogni sezione basta scrivere questo

flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 0.0,10,0);

quando usi UICollectionReusableView del tipo UICollectionElementKindSectionFooter, la tua soluzione non funzionerà
Pratik Jamariya

-1
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {       
         return UIEdgeInsetsMake(7, 10, 5, 10);    
   }
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.