UICollectionView margens de espaçamento

181

Eu tenho um UICollectionViewque mostra fotos. Eu criei a coleção usando UICollectionViewFlowLayout. Funciona bem, mas eu gostaria de ter espaçamento nas margens. É possível fazer isso usando UICollectionViewFlowLayoutou devo implementar o meu UICollectionViewLayout?

Mert
fonte

Respostas:

333

Você pode usar o collectionView:layout:insetForSectionAtIndex:método para você UICollectionViewou definir a sectionInsetpropriedade do UICollectionViewFlowLayoutobjeto anexado ao seu 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)];

Atualizado para o Swift 5

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
       return UIEdgeInsets(top: 25, left: 15, bottom: 0, right: 5)
    }
michael23
fonte
35
Parece que não estou conseguindo inserir as setas esquerda e direita para trabalhar ao usar um layout de fluxo vertical ... #
John
1
Agora, substituir o método sectionInset de UICollectionViewFlowLayout subclassed também não tem efeito. A propriedade de configuração descrita abaixo funciona.
Dren 29/04
4
NB: lembre-se de adicionar UICollectionViewDelegateFlowLayoutà sua lista de delegados viewcontroller usar o métodoinsetForSectionAtIndex
David Douglas
98

Configurando inserções no Interface Builder, como mostrado na captura de tela abaixo

Definindo inserções de seção para UICollectionView

Irá resultar em algo como isto:

Uma célula de exibição de coleção com inserções de seção

krzymar
fonte
2
Ótima resposta, só queria ressaltar que você também terá que jogar com espaçamento mínimo para que a seção de seção funcione bem.
Smit Yash
75

Para adicionar espaçamento no todo UICollectionView :

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

Para brincar com o espaçamento entre elementos da mesma linha (coluna se você estiver rolando horizontalmente) e seus tamanhos:

flow.itemSize = ...;
flow.minimumInteritemSpacing = ...;
marmor
fonte
5
Isso funciona, mas as collection.collectionViewLayoutnecessidades de um elenco como no exemplo por @Pooja: UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) self.collectionViewLayout;
JWJ
Fundição em 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

EDIT XCode 11.4 e swift 5

let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

não funciona Use abaixo obras.

let flow = UICollectionViewFlowLayout()

insira a descrição da imagem aqui

William Hu
fonte
Existe uma maneira de definir a cor para o espaçamento?
Martín Serrano
1
@ MartínDaniel Basta definir o backgroundColordo collectionView. Ou qualquer que seja a super visão.
William Hu
1
mas não há margens nas bordas
user924
@ user924 As margens nas arestas podem ser definidas com UIEdgeInsets (superior: esquerda: inferior: direita:). Se rolar verticalmente, defina as inserções esquerda / direita. Se estiver rolando horizontalmente, defina as inserções superior e inferior.
Marcy
40

Apenas para corrigir algumas informações erradas nesta página:

1- minimumInteritemSpacing : o espaçamento mínimo a ser usado entre os itens na mesma linha.

O valor padrão: 10.0.

(Para uma grade de rolagem vertical, esse valor representa o espaçamento mínimo entre os itens na mesma linha.)

2- minimumLineSpacing : o espaçamento mínimo a ser usado entre linhas de itens na grade.

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

Felix
fonte
2
Isso não parece afetar o espaçamento entre as seções, apenas entre itens dentro da mesma seção?
Crashalot 18/01/16
@Crashalot - você tem certeza que não quer dizer minimumLineSpacing? ou seja, cada linha de células? Também há opções para Insertos de Seção, se você realmente estiver usando seções.
Chucky
Isso funcionou para mim através da interface do storyboard. Eu estava procurando uma solução para visualizações de coleção horizontais apenas. Obrigado +10
kemicofa ghost
9

Cálculo de layout automático rápido e moderno

Embora esse tópico já contenha várias respostas úteis, quero adicionar uma versão Swift moderna , com base na resposta de William Hu. Também melhora duas coisas:

  • O espaçamento entre linhas diferentes agora sempre corresponderá ao espaçamento entre itens na mesma linha.
  • Ao definir uma largura mínima, o código calcula automaticamente o número de itens em uma linha e aplica esse estilo ao layout do fluxo.

Aqui está o 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
fonte
Se itemsInOneLinefor 1, isso resultará em um NaN devido à divisão por zero aqui:itemsInOneLine / (itemsInOneLine - 1)
TylerJames
1
@TylerJames Thanks! Eu ajustei o código para corrigir o problema;)
fredpi 05/02
8

use setMinimumLineSpacing:e setMinimumInteritemSpacing:no UICollectionViewFlowLayout-Object.

Jonathan Cichon
fonte
Não, não funciona, como esperado. setMinimumLineSpacing é: O espaçamento mínimo a ser usado entre itens na mesma linha. E setMinimumInteritemSpacing é: O espaçamento mínimo a ser usado entre as linhas de itens na grade. Minha pergunta é sobre margens, não espaço entre elementos. por exemplo. Espaçamento esquerdo e superior do primeiro elemento.
Mert
assumindo um srollDirection vertical, você pode usar contentInset para espaçamento superior e inferior da primeira e da última linha. Além disso, você pode adicionar suas margens em suas células.
precisa
8

Usando collectionViewFlowLayout.sectionInsetou collectionView:layout:insetForSectionAtIndex:está correto.

No entanto, se o seu collectionView tiver várias seções e você desejar adicionar margem a todo o collectionView, recomendo usar o 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
fonte
5

Para colocar espaço entre CollectionItems, use este

escreva estas duas linhas em viewdidload

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

Defina a insetForSectionAtpropriedade do UICollectionViewFlowLayoutobjeto anexado ao seuUICollectionView

Certifique-se de adicionar 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)
    }

Objetivo - C

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

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

Tudo o que você precisa fazer é alterar o valor itemsPerRow e ele atualizará o número de itens por linha de acordo. Além disso, você pode alterar o valor do espaçamento, se desejar um espaçamento mais ou menos geral.

insira a descrição da imagem aqui insira a descrição da imagem aqui

ScottyBlades
fonte
1
Bom ... é um trabalho perfeito.
sohil 16/02
1

Para adicionar margens às células especificadas, você pode usar esse layout de fluxo 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
fonte
0

No swift 4 e no autoLayout, você pode usar o sectionInset assim:

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

Para adicionar uma separação de 10 px entre cada seção, basta escrever este

flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 0.0,10,0);
Gal Blank
fonte
quando se utiliza UICollectionReusableView de tipo UICollectionElementKindSectionFooter, sua solução não vai funcionar
Pratik Jamariya
-1
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {       
         return UIEdgeInsetsMake(7, 10, 5, 10);    
   }
vishal
fonte