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.