CollectionView sizeForItemAtIndexPath non è mai stato chiamato


94

Questo mi sta facendo impazzire! Ho un UICollectionViewController come mostrato di seguito:

class PhrasesCompactCollectionViewController: UICollectionViewController

Il numberOfSections e il cellForItemAt vengono chiamati ma il sizeForItemAtIndexPath non viene mai chiamato. Sto usando lo stesso codice esatto da qualche altra parte e si attiva correttamente. Sto usando Xcode 8 Beta 6.

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

        return CGSize(width: 120, height:120) 
    }

Risposte:


251

È necessario specificare di implementare il protocollo UICollectionViewDelegateFlowLayoutnella dichiarazione della classe.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout


10
L'ho fatto ma non viene ancora chiamato. :(
Van Du Tran

57

In Swift 3+ Usa questo metodo:

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

Assicurati che la tua classe sia conforme sia a Delegate

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout


4
È ridondante da rispettare UICollectionViewDelegatecome già fa UICollectionViewController.
Van Du Tran

3
@VanDuTran Non è ridondante affermare che è necessario perché non è necessario essere un UICollectionViewController ...
Michael Hudson

Penso che volevi dire che una vista non raccolta, Viewcontroller può essere UICollectionViewDelegate.
ScottyBlades

1
UICollectionViewDelegateFlowLayout eredita da UICollectionViewDelegate quindi implementa semplicemente UICollectionViewDelegateFlowLayout
evya

46

Ho avuto lo stesso problema. L'unica cosa che mi ha aiutato è stata creare la "Dimensione stimata" per la dimensione della cella sotto l'ispettore di dimensioni collectionView "Nessuno".

inserisci qui la descrizione dell'immagine


8
Hai salvato il mio compagno di giornata, sei un eroe
Asif Ali

1
In qualche modo tutte le altre risposte su tutti gli altri post sull'utilizzo sizeForItemAtnon hanno menzionato questo. Molto utile.
JCutting8

Questo è pazzesco!!!! Ho provato sul simulatore di iPhone 5 con la versione iOS 10.3.1 e il metodo è stato chiamato. su iPhone 5s il simulatore con il metodo della versione 10.3.1 non viene chiamato !!! Ho modificato le dimensioni stimate su Nessuno. Ha iniziato a essere chiamato su iPhone 5s. WT WT WT
hasan

Molte grazie! La mia vista della raccolta con personalizzato ha sizeForItemAtfunzionato bene fino a Xcode 11.4 quando improvvisamente le celle avevano una larghezza sbagliata. Ho provato un sacco di cose e finalmente ha funzionato.
Filip

Mi hai risparmiato tempo. Molte grazie.
Shahbaz Akram il

15

Swift 3

Per impostare la dimensione della cella di UICollectionView, è necessario creare e personalizzare l'oggetto di UICollectionViewFlowLayout. Personalizza le proprietà e imposta quell'oggetto layout sull'oggetto UICollectionView.

Modificare gli oggetti cellheight e cell cellWidth in base alle proprie esigenze (l'altezza e la larghezza della cella desiderate).

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()
}

Assicurati: se hai aggiunto il metodo sizeForItemAt indexPath, devi RIMUOVERE il metodo ...

Rimuovi il metodo sottostante

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

}

12
In che modo è utile?
almas

1
Almas, questo sarà utile per impostare la dimensione della cella personalizzata di UICollectionViewCell ... Ci sono variabili cellWidth e cellHeight, in cui puoi definire i tuoi valori ... Così come "layout.sectionInset", "layout.minimumLineSpacing" e "layout .minimumInteritemSpacing ", queste variabili sono importanti anche per le dimensioni di UICollectionViewCell ..
Gaurav Rami

2
Funziona solo se tutte le celle hanno le stesse dimensioni. La risposta sotto è la risposta corretta
JeffN

questo serve per cambiare la dimensione di UICollectionView ma non la cella all'interno della vista
Async-

Questa non è una risposta al motivo per cui il metodo delegato non è chiamato
Ziv Kesten

12

Swift 5

Tutti questi passaggi sono necessari :

  1. Conforme a UICollectionViewDelegateFlowLayout <== Assolutamente necessario !!
  2. e a UICollectionViewDelegate, UICollectionViewDataSource
  3. Impostali in viewDidLoad: collectionView.delegate = selfecollectionView.dataSource = self
  4. Impostare Dimensioni stimate su Nessuno in Interface Builder
  5. Assicurati che il seguente metodo abbia sizeForItemAt e non sizeForItemAtIndexPath

come :

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

2
Stima la dimensione su Nessuno - salva la mia giornata!
Joe Hallenbeck,

6

La prima classe deve confermare a UICollectionViewDelegateFlowLayout. Quindi è necessario scrivere il seguente codice in viewDidLoad ():

// Per dire a UICollectionView di utilizzare i metodi UICollectionViewDelegateFlowLayout di UIViewController

collectionView.delegate = self

// Se si desidera impostare il proprio layout del flusso di visualizzazione della raccolta

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

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

Utilizzando questo codice, il metodo UICollectionViewDelegateFlowLayout

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

verrà chiamato, puoi impostare la dimensione in questo metodo.


4

Tre cose che devi controllare se nessuna risposta funziona:

  1. Implementare il delegato FlowLayout: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Usa il metodo per la dimensione dell'articolo per 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. Selezionare Estimate size = Nonenell'elemento Inspect di UICollectionView.


2

Ho avuto lo stesso problema e niente lo avrebbe risolto. Ho ricevuto un avviso giallo che diceva di renderlo privato perché si avvicinava a un'altra funzione definita dal delegato del layout. Quello che mi ha risolto è stato:

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

Notare la differenza tra "sizeForItemAtIndexPath" e "sizeForItemAt" corretto.

Mi sono strappato i capelli per giorni cercando di capirlo e alla fine ha funzionato. Di seguito includerò tutte le mie funzioni per mostrarti come ho anche "nascosto" una cella rendendo l'altezza uguale 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)
    }
}

0

Ho avuto questo problema la scorsa notte. Alla fine l'ho risolto a mezzanotte quando mi sono reso conto che il metodo "didSelectItemAtIndex" non era chiuso con una parentesi di chiusura "}"

Ho aggiunto una parentesi di chiusura in fondo alla classe quando mi è stato chiesto dall'errore di compilazione. Quindi in effetti tutti i metodi sotto "didSelectItemAtIndex" erano all'interno di quel metodo.

Pubblicando qui solo nel caso in cui qualcun altro spreca 4 ore delle loro serate su questo :-(


0

Assicurati di metterlo in viewDidLoad ()

collectionView.delegate = self

0

il mio problema era che avevo il mio oggetto UICollectionViewDataSource creato come variabile locale. Quindi, se inizializzi manualmente il tuo oggetto dataSource nel codice, assicurati di memorizzarlo come variabile globale.


0

Usa questo metodo

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

}

Invece di

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

}

0

Basta aggiungere: UICollectionViewDelegateFlowLayout

class YourClass: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {}

-11

Per me (in Swift 3.1) il metodo deve essere dichiarato pubblico in questo modo:

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

Non dimenticare di renderlo pubblico .


publicè ciò che usi per rendere il tuo codice accessibile tra framework e moduli.
ScottyBlades
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.