UICollectionView les marges d'espacement

181

J'ai un UICollectionViewqui montre des photos. J'ai créé la collectionview en utilisant UICollectionViewFlowLayout. Cela fonctionne bien mais j'aimerais avoir un espacement sur les marges. Est-il possible de le faire en utilisant UICollectionViewFlowLayoutou dois-je implémenter le mien UICollectionViewLayout?

Mert
la source

Réponses:

333

Vous pouvez utiliser la collectionView:layout:insetForSectionAtIndex:méthode pour votre UICollectionViewou définir la sectionInsetpropriété de l' UICollectionViewFlowLayoutobjet attaché à votre UICollectionView:

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

ou

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

Mis à jour pour Swift 5

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
       return UIEdgeInsets(top: 25, left: 15, bottom: 0, right: 5)
    }
michael23
la source
35
Je ne semble pas faire fonctionner les encarts gauche et droit lors de l'utilisation d'une disposition de flux vertical ...
John
1
La substitution de la méthode sectionInset de UICollectionViewFlowLayout sous-classée n'a également aucun effet. La propriété de réglage décrite ci-dessous fonctionne.
Dren
4
NB: n'oubliez pas d'ajouter UICollectionViewDelegateFlowLayoutà votre liste de délégués ViewController pour utiliser la méthodeinsetForSectionAtIndex
David Douglas
98

Configuration des inserts dans Interface Builder comme indiqué dans la capture d'écran ci-dessous

Paramétrage des inserts de section pour UICollectionView

Cela donnera quelque chose comme ceci:

Une cellule de vue de collection avec des incrustations de section

Krzymar
la source
2
Excellente réponse, je voulais juste souligner que vous devrez également jouer avec un espacement minimum pour que l'encart de section fonctionne bien.
Smit Yash
75

Pour ajouter un espacement sur l' ensemble UICollectionView :

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

Pour jouer avec l'espacement entre les éléments d'une même ligne (colonne si vous faites défiler horizontalement), et leurs tailles:

flow.itemSize = ...;
flow.minimumInteritemSpacing = ...;
marmor
la source
5
Cela fonctionne, mais il collection.collectionViewLayoutfaut un casting comme dans l'exemple de @Pooja: UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) self.collectionViewLayout;
jwj
Casting in Swiftif 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

MODIFIER XCode 11.4 et swift 5

let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

ne fonctionne pas. Utilisez ci-dessous fonctionne.

let flow = UICollectionViewFlowLayout()

entrez la description de l'image ici

William Hu
la source
Existe-t-il un moyen de définir la couleur de l'espacement?
Martín Serrano
1
@ MartínDaniel Il suffit de régler le backgroundColordu collectionView. Ou quelle que soit la vue superbe.
William Hu
1
mais il n'y a pas de marges sur les bords
user924
@ user924 Les marges aux bords peuvent être définies avec UIEdgeInsets (haut: gauche: bas: droite:). Si vous faites défiler verticalement, définissez les encarts gauche / droite. Si vous faites défiler horizontalement, définissez les inserts du haut et du bas.
Marcy
40

Juste pour corriger certaines informations erronées dans cette page:

1- minimumInteritemSpacing : L'espacement minimum à utiliser entre les éléments de la même ligne.

La valeur par défaut: 10,0.

(Pour une grille à défilement vertical, cette valeur représente l'espacement minimum entre les éléments d'une même ligne.)

2- minimumLineSpacing : L'espacement minimum à utiliser entre les lignes d'éléments dans la grille.

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

Félix
la source
2
Cela ne semble pas affecter l'espacement entre les sections, uniquement entre les éléments d'une même section?
Crashalot
@Crashalot - êtes-vous sûr de ne pas parler de minimumLineSpacing? c'est-à-dire chaque ligne de cellules? Il existe également des options pour les encarts de section si vous utilisez vraiment des sections.
Chucky
Cela a fonctionné pour moi en le faisant via l'interface du storyboard. Je cherchais une solution pour les vues de collection uniquement horizontales. Merci +10
kemicofa ghost
9

Calcul de disposition automatique et rapide moderne

Bien que ce fil contienne déjà un tas de réponses utiles, je souhaite ajouter une version moderne de Swift , basée sur la réponse de William Hu. Cela améliore également deux choses:

  • L'espacement entre les différentes lignes correspondra désormais toujours à l'espacement entre les éléments de la même ligne.
  • En définissant une largeur minimale, le code calcule automatiquement le nombre d'éléments dans une ligne et applique ce style à la disposition du flux.

Voici le code:

// 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)
Fredpi
la source
Si itemsInOneLinevaut 1, cela entraînera un NaN en raison de la division par zéro ici:itemsInOneLine / (itemsInOneLine - 1)
TylerJames
1
@TylerJames Merci! J'ai ajusté le code pour résoudre le problème;)
fredpi
8

utiliser setMinimumLineSpacing:et setMinimumInteritemSpacing:sur le UICollectionViewFlowLayout-Object.

Jonathan Cichon
la source
Non, cela ne fonctionne pas, comme prévu. setMinimumLineSpacing est: L'espacement minimum à utiliser entre les éléments d'une même ligne. Et setMinimumInteritemSpacing est: L'espacement minimum à utiliser entre les lignes d'éléments de la grille. Ma question concerne les marges et non l'espace entre les éléments. par exemple. Espacement gauche et supérieur du premier élément.
Mert
en supposant une srollDirection verticale, vous pouvez utiliser contentInset pour l'espacement haut et bas de la première et de la dernière ligne. Vous pouvez également ajouter vos marges dans vos cellules.
Jonathan Cichon
8

Utilisation collectionViewFlowLayout.sectionInsetou collectionView:layout:insetForSectionAtIndex:sont corrects.

Cependant, si votre collectionView a plusieurs sections et que vous souhaitez ajouter une marge à l'ensemble de collectionView, je recommande d'utiliser le 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);
vmeyer
la source
5

Pour mettre de l'espace entre les CollectionItems, utilisez ceci

écrivez ces deux lignes dans viewdidload

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

Définissez la insetForSectionAtpropriété de l' UICollectionViewFlowLayoutobjet attaché à votreUICollectionView

Assurez-vous d'ajouter ce protocole

UICollectionViewDelegateFlowLayout

Rapide

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

Objectif c

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

En 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;

Tout ce que vous avez à faire est de modifier la valeur itemsPerRow et il mettra à jour le nombre d'éléments par ligne en conséquence. De plus, vous pouvez modifier la valeur d'espacement si vous souhaitez un espacement plus ou moins général.

entrez la description de l'image ici entrez la description de l'image ici

ScottyBlades
la source
1
Bien ... c'est parfait.
sohil
1

Pour ajouter des marges aux cellules spécifiées, vous pouvez utiliser cette disposition de flux personnalisée. 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
    }
}
Myrddin
la source
0

Dans swift 4 et autoLayout, vous pouvez utiliser sectionInset comme ceci:

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
Mohsen mokhtari
la source
-1

Pour ajouter une séparation de 10 pixels entre chaque section, écrivez simplement ceci

flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 0.0,10,0);
Gal Blank
la source
lorsque vous utilisez UICollectionReusableView de type UICollectionElementKindSectionFooter, votre solution ne fonctionnera pas
Pratik Jamariya
-1
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {       
         return UIEdgeInsetsMake(7, 10, 5, 10);    
   }
vishal
la source