CollectionView sizeForItemAtIndexPath nunca chamado

92

Isto está me enlouquecendo! Eu tenho um UICollectionViewController conforme mostrado abaixo:

class PhrasesCompactCollectionViewController: UICollectionViewController

NumberOfSections e cellForItemAt estão sendo chamados, mas sizeForItemAtIndexPath nunca é chamado. Estou usando exatamente o mesmo código em outro lugar e ele dispara corretamente. Estou usando o Xcode 8 Beta 6.

func collectionView(collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAtIndexPath indexPath:  NSIndexPath) -> CGSize {

        return CGSize(width: 120, height:120) 
    }
john doe
fonte

Respostas:

250

Você precisa especificar que implementa o protocolo UICollectionViewDelegateFlowLayoutem sua declaração de classe.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout

almas
fonte
10
Eu fiz isso, mas ainda não foi chamado. :(
Van Du Tran
57

Em Swift 3+, use este método:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width:(collectionView.frame.height-90)/2, height: 100)
}

Certifique-se de que sua classe está em conformidade com ambos Delegado

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout

Shiv Kumar
fonte
4
É redundante obedecer ao UICollectionViewDelegateUICollectionViewController.
Van Du Tran
2
@VanDuTran Não é redundante afirmar que é necessário porque ser um UICollectionViewController não é necessário ...
Michael Hudson
Eu acho que você quis dizer que uma visão sem coleção, Viewcontroller pode ser o UICollectionViewDelegate.
ScottyBlades de
1
UICollectionViewDelegateFlowLayout herda de UICollectionViewDelegate, então apenas implemente o UICollectionViewDelegateFlowLayout
evya
43

Eu tive o mesmo problema. A única coisa que me ajudou foi fazer o 'Tamanho estimado' para o tamanho da célula no inspetor de tamanho de collectionView 'Nenhum'.

insira a descrição da imagem aqui

Zenman C
fonte
8
Você salvou meu dia, amigo, você é um herói
Asif Ali
1
De alguma forma, todas as outras respostas em todas as outras postagens sobre o uso sizeForItemAtnão mencionaram isso. Muito útil.
JCutting8
Isso é loucura!!!! Testei no simulador do iPhone 5 com a versão 10.3.1 iOS e o método foi chamado. no simulador do iPhone 5s com o método da versão 10.3.1 não é chamado !!! Mudei o tamanho estimado para nenhum. Ele começou a ser chamado no iPhone 5s. WT WT WT
hasan
Muito obrigado! Minha visualização de coleção com customização sizeForItemAtfuncionou bem até o Xcode 11.4 quando de repente as células estavam com a largura errada. Tentei um monte de coisas e isso finalmente funcionou.
Filip
Você salvou meu tempo. Muito obrigado.
Shahbaz Akram
15

Swift 3

Para definir o tamanho da célula de UICollectionView, você precisa criar e personalizar o objeto de UICollectionViewFlowLayout. Personalize as propriedades e defina esse objeto de layout para o objeto UICollectionView.

Altere os objetos cellheight e cellWidth da célula de acordo com seus requisitos (a altura e largura da célula que você deseja).

override func viewDidLoad() {
    super.viewDidLoad()

    let cellWidth : CGFloat = myCollectionView.frame.size.width / 4.0
    let cellheight : CGFloat = myCollectionView.frame.size.height - 2.0
    let cellSize = CGSize(width: cellWidth , height:cellheight)

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical //.horizontal
    layout.itemSize = cellSize
    layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
    layout.minimumLineSpacing = 1.0
    layout.minimumInteritemSpacing = 1.0
    myCollectionView.setCollectionViewLayout(layout, animated: true)

    myCollectionView.reloadData()
}

Certifique-se: se você adicionou o método sizeForItemAt indexPath, então deve REMOVER o método ...

Remover Método Abaixo

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

}
Gaurav Rami
fonte
12
Como isso é útil?
almas,
1
Almas, isso será útil para definir o tamanho de célula personalizado de UICollectionViewCell ... Existem variáveis ​​cellWidth e cellHeight, em que você pode definir seus próprios valores ... Bem como "layout.sectionInset", "layout.minimumLineSpacing" e "layout .minimumInteritemSpacing ", essas variáveis ​​também são importantes para o tamanho de UICollectionViewCell.
Gaurav Rami
2
Isso só funciona se todas as células tiverem o mesmo tamanho. A resposta abaixo é a correta
JeffN
isso é para alterar o tamanho do UICollectionView, mas não da célula dentro da visualização
Async-
Esta não é uma resposta ao motivo pelo qual o método delegado não é chamado
Ziv Kesten
10

Swift 5

Todas essas etapas são necessárias :

  1. Em conformidade com UICollectionViewDelegateFlowLayout <== Absolutamente necessário !!
  2. e para UICollectionViewDelegate, UICollectionViewDataSource
  3. Defina-os em viewDidLoad: collectionView.delegate = selfecollectionView.dataSource = self
  4. Defina o tamanho estimado como nenhum no construtor de interface
  5. Certifique-se de que o método a seguir tenha sizeForItemAt e não sizeForItemAtIndexPath

Como :

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    return CGSize(width: 100, height:100)
} 
Xys
fonte
1
Estimar o tamanho para nenhum - salve o meu dia!
Joe Hallenbeck
6

A primeira classe precisa confirmar para UICollectionViewDelegateFlowLayout. Então você precisa escrever o seguinte código em viewDidLoad ():

// Para dizer ao UICollectionView para usar os métodos UICollectionViewDelegateFlowLayout do seu UIViewController

collectionView.delegate = self

// Se você deseja definir seu próprio layout de fluxo de visualização de coleção

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //depending upon direction of collection view

self.collectionView?.setCollectionViewLayout(layout, animated: true)

Usando este método de código UICollectionViewDelegateFlowLayout

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

será chamado, você pode definir o tamanho neste método.

HS Progr
fonte
4

Três coisas que você precisa verificar se nenhuma resposta funcionar:

  1. Implemente o Delegado FlowLayout: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Use o método para o tamanho do item para swift 3.0+: func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: (collectionView.frame.width / 3) - 1, height: collectionView.frame.width) }

  3. Selecione Estimate size = Noneno elemento Inspecionar de UICollectionView.

Manish
fonte
2

Eu tive o mesmo problema e nada resolveria. Recebi um aviso amarelo dizendo para torná-lo privado porque se aproximava de outra função definida pelo Delegado de Layout. O que consertou para mim foi:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

Observe a diferença de "sizeForItemAtIndexPath" para o "sizeForItemAt" correto.

Eu arranquei meu cabelo por dias tentando descobrir isso e finalmente funcionou. Abaixo, incluirei todas as minhas funções para mostrar como também "escondi" uma célula tornando a altura igual a 0.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let findIndex = labelArray.index(of: "\(labelArray[indexPath.row])")
    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width

    if (findIndex! % 2 == 0){
        // Even index, show cell
        return CGSize(width: screenWidth, height: 246)
    }
    else {
        return CGSize(width: screenWidth, height: 0)
    }
}
Stephen Rains
fonte
0

Eu tive esse problema na noite passada. Finalmente resolvi à meia-noite quando percebi que o método 'didSelectItemAtIndex' não estava fechado com um colchete de fechamento "}"

Eu adicionei um colchete de fechamento na parte inferior da classe quando questionado pelo erro de compilação. Portanto, todos os métodos abaixo de 'didSelectItemAtIndex' estavam dentro desse método.

Postando aqui apenas no caso de alguém perder 4 horas de suas noites com este aqui :-(

Charlie Seligman
fonte
0

Certifique-se de colocá-lo em viewDidLoad ()

collectionView.delegate = self
Azam
fonte
0

meu problema era que eu tinha meu objeto UICollectionViewDataSource criado como variável local. Portanto, se você inicializar seu objeto dataSource manualmente no código, certifique-se de armazená-lo como uma variável global.

Petro Darchyn
fonte
0

Use este método

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

}

Ao invés de

private func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

}
Abdul Malik Aman
fonte
-11

Para mim (no Swift 3.1), o método deve ser declarado público assim:

    public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
       return CGSize()
    }

Não se esqueça de torná-lo público .

Oliver Eichhorn
fonte
publicé o que você usa para tornar seu código acessível entre estruturas e módulos.
ScottyBlades