UICollectionView márgenes de espaciado

181

Tengo una UICollectionViewque muestra fotos. He creado la vista de colección usando UICollectionViewFlowLayout. Funciona bien, pero me gustaría tener espacios en los márgenes. ¿Es posible hacer eso usandoUICollectionViewFlowLayout o debo implementar el mío UICollectionViewLayout?

Mert
fuente

Respuestas:

333

Puede usar el collectionView:layout:insetForSectionAtIndex:método para su UICollectionViewo establecer la sectionInsetpropiedad del UICollectionViewFlowLayoutobjeto adjunto a su 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)];

Actualizado para Swift 5

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
       return UIEdgeInsets(top: 25, left: 15, bottom: 0, right: 5)
    }
michael23
fuente
35
No parece que las inserciones izquierda y derecha funcionen cuando uso un diseño de flujo vertical ...
John
1
Ahora anular el método sectionInset de UICollectionViewFlowLayout subclase tampoco tiene ningún efecto. La propiedad de configuración descrita a continuación funciona.
Dren
44
NB: recuerde agregar UICollectionViewDelegateFlowLayouta su lista de delegados de ViewController para usar el métodoinsetForSectionAtIndex
David Douglas
98

Configuración de inserciones en Interface Builder como se muestra en la captura de pantalla a continuación

Configuración de inserciones de sección para UICollectionView

Resultará en algo como esto:

Una celda de vista de colección con inserciones de sección

krzymar
fuente
2
Gran respuesta, solo quería señalar que también tendrás que jugar con un espaciado mínimo para que el recuadro de la sección funcione bien.
Smit Yash
75

Para agregar espaciado en todo UICollectionView :

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

Para jugar con el espacio entre elementos de la misma fila (columna si se desplaza horizontalmente) y sus tamaños:

flow.itemSize = ...;
flow.minimumInteritemSpacing = ...;
marmor
fuente
55
Esto funciona, pero collection.collectionViewLayoutnecesita un reparto como en el ejemplo de @Pooja: UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) self.collectionViewLayout;
jwj
Casting en 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

EDITAR XCode 11.4 y swift 5

let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

no funciona Utilice a continuación obras.

let flow = UICollectionViewFlowLayout()

ingrese la descripción de la imagen aquí

William Hu
fuente
¿Hay alguna manera de establecer el color en el espacio?
Martín Serrano
1
@ MartínDaniel Acaba de configurar el backgroundColorde la collectionView. O lo que sea la super vista.
William Hu
1
pero no hay márgenes en los bordes
usuario924
@ user924 Los márgenes en los bordes se pueden establecer con UIEdgeInsets (arriba: izquierda: abajo: derecha:). Si se desplaza verticalmente, configure las inserciones izquierda / derecha. Si se desplaza horizontalmente, configure las inserciones superior e inferior.
Marcy
40

Solo para corregir información incorrecta en esta página:

1- minimalInteritemSpacing : el espaciado mínimo para usar entre elementos en la misma fila.

El valor predeterminado: 10.0.

(Para una cuadrícula de desplazamiento vertical, este valor representa el espacio mínimo entre los elementos en la misma fila).

2- minimalLineSpacing : el espaciado mínimo para usar entre líneas de elementos en la cuadrícula.

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

Felix
fuente
2
¿Esto no parece afectar el espacio entre secciones, solo entre elementos dentro de la misma sección?
Crashalot
@Crashalot: ¿estás seguro de que no quieres decir minimalLineSpacing? es decir, cada línea de células? También hay opciones para los recuadros de sección si realmente está utilizando secciones.
Chucky
Esto funcionó para mí hacerlo a través de la interfaz del guión gráfico. Estaba buscando una solución para vistas de colección solo horizontales. Gracias +10
kemicofa fantasma
9

Swift moderno, cálculo de diseño automático

Si bien este hilo ya contiene un montón de respuestas útiles, quiero agregar una versión Swift moderna , basada en la respuesta de William Hu. También mejora dos cosas:

  • El espacio entre diferentes líneas ahora siempre coincidirá con el espacio entre los elementos en la misma línea.
  • Al establecer un ancho mínimo, el código calcula automáticamente el número de elementos en una fila y aplica ese estilo al diseño del flujo.

Aquí está el código:

// 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
fuente
Si itemsInOneLinees 1, esto dará como resultado un NaN debido a la división por cero aquí:itemsInOneLine / (itemsInOneLine - 1)
TylerJames
1
@TylerJames ¡Gracias!
Ajusté
8

use setMinimumLineSpacing:y setMinimumInteritemSpacing:en el UICollectionViewFlowLayout-Objeto.

Jonathan Cichon
fuente
No, no funciona, como se esperaba. setMinimumLineSpacing es: El espacio mínimo para usar entre elementos en la misma fila. Y setMinimumInteritemSpacing es: El espacio mínimo para usar entre líneas de elementos en la cuadrícula. Mi pregunta es sobre márgenes, no espacio entre elementos. p.ej. Espaciado izquierdo y superior del primer elemento.
Mert
suponiendo una dirección sroll vertical puede usar contentInset para el espaciado superior e inferior de la primera y la última fila. También puede agregar sus márgenes en sus Celdas.
Jonathan Cichon
8

Usando collectionViewFlowLayout.sectionInseto collectionView:layout:insetForSectionAtIndex:son correctos.

Sin embargo, si su collectionView tiene varias secciones y desea agregar margen a todo el collectionView, le recomiendo usar el 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
fuente
5

Para poner espacio entre CollectionItems use esto

escribe estas dos líneas en viewdidload

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

Establezca la insetForSectionAtpropiedad del UICollectionViewFlowLayoutobjeto adjunto a suUICollectionView

Asegúrate de agregar este protocolo

UICollectionViewDelegateFlowLayout

Rápido

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

C objetivo

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

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

Todo lo que tiene que hacer es cambiar el valor de itemsPerRow y actualizará el número de elementos por fila en consecuencia. Además, puede cambiar el valor de espaciado si desea un espaciado más o menos general.

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

ScottyBlades
fuente
1
Bien ... es un trabajo perfecto.
Sohil
1

Para agregar márgenes a las celdas especificadas, puede usar este diseño de flujo personalizado. 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
fuente
0

En swift 4 y autoLayout, puede usar sectionInset de esta manera:

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
fuente
-1

Para agregar una separación de 10px entre cada sección simplemente escriba esto

flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 0.0,10,0);
Gal Blank
fuente
cuando use UICollectionReusableView del tipo UICollectionElementKindSectionFooter, su solución no funcionará
Pratik Jamariya
-1
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {       
         return UIEdgeInsetsMake(7, 10, 5, 10);    
   }
vishal
fuente