CollectionView sizeForItemAtIndexPath jamais appelée

94

Ça me rend fou! J'ai un UICollectionViewController comme indiqué ci-dessous:

class PhrasesCompactCollectionViewController: UICollectionViewController

Les numberOfSections et cellForItemAt sont appelés mais le sizeForItemAtIndexPath n'est jamais appelé. J'utilise le même code exact ailleurs et il se déclenche correctement. J'utilise Xcode 8 Beta 6.

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

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

Réponses:

251

Vous devez spécifier que vous implémentez le protocole UICollectionViewDelegateFlowLayoutdans votre déclaration de classe.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout

almas
la source
10
J'ai fait ça mais ça ne s'appelle toujours pas. :(
Van Du Tran
57

Dans Swift 3+, utilisez cette méthode:

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

Assurez-vous que votre classe respecte les deux

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout

Shiv Kumar
la source
4
Il est redondant de se conformer à UICollectionViewDelegatecomme le fait déjà UICollectionViewController.
Van Du Tran
3
@VanDuTran Il n'est pas redondant de déclarer que c'est nécessaire car il n'est pas nécessaire d'être un UICollectionViewController ...
Michael Hudson
Je pense que vous vouliez dire qu'une vue sans collection, Viewcontroller peut être le UICollectionViewDelegate.
ScottyBlades
1
UICollectionViewDelegateFlowLayout hérite de UICollectionViewDelegate donc implémentez simplement UICollectionViewDelegateFlowLayout
evya
46

J'ai eu le même problème. La seule chose qui m'a aidé a été de faire la «Taille estimée» pour la Taille de la cellule sous l'inspecteur de taille de collectionView «Aucune».

entrez la description de l'image ici

Zenman C
la source
8
Vous avez sauvé mon pote de jour, vous êtes un héros
Asif Ali
1
D'une manière ou d'une autre, toutes les autres réponses sur tous les autres messages sur l'utilisation sizeForItemAtn'ont pas mentionné cela. Très utile.
JCutting8
C'est fou!!!! J'ai testé sur un simulateur iPhone 5 avec la version iOS 10.3.1 et la méthode est appelée. sur le simulateur iPhone 5s avec la méthode de la version 10.3.1 ne se fait pas appeler !!! J'ai changé la taille de l'estimation sur Aucune. Il a commencé à être appelé sur l'iPhone 5s. WT WT WT
hasan
Merci beaucoup! Ma vue de collection avec la personnalisation sizeForItemAtfonctionnait bien jusqu'à Xcode 11.4 lorsque soudainement les cellules n'avaient pas la largeur. J'ai essayé un tas de choses et cela a finalement fonctionné.
Filip le
Vous avez sauvé mon temps. Merci beaucoup.
Shahbaz Akram
15

Swift 3

Pour définir la taille de cellule de UICollectionView, vous devez créer et personnaliser l'objet de UICollectionViewFlowLayout. Personnalisez les propriétés et définissez cet objet de mise en page sur l'objet UICollectionView.

Modifiez les objets cellheight et cell cellWidth en fonction de vos besoins (la hauteur et la largeur de cellule souhaitées).

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

Assurez-vous: si vous avez ajouté la méthode sizeForItemAt indexPath, vous devez SUPPRIMER la méthode ...

Supprimer la méthode ci-dessous

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

}
Gaurav Rami
la source
12
En quoi cela est-il utile?
almas
1
Almas, cela sera utile pour définir la taille de cellule personnalisée de UICollectionViewCell ... Il existe des variables cellWidth et cellHeight, dans lesquelles vous pouvez définir vos propres valeurs ... Ainsi que "layout.sectionInset", "layout.minimumLineSpacing" et "layout .minimumInteritemSpacing ", ces variables comptent également pour la taille de UICollectionViewCell.
Gaurav Rami
2
Cela ne fonctionne que si toutes les cellules ont la même taille. La réponse ci-dessous est la bonne réponse
JeffN
c'est pour changer la taille de UICollectionView mais pas la cellule à l'intérieur de la vue
Async-
Ce n'est pas une réponse à la raison pour laquelle la méthode déléguée n'est pas appelée
Ziv Kesten
12

Swift 5

Toutes ces étapes sont nécessaires :

  1. Conforme à UICollectionViewDelegateFlowLayout <== Absolument nécessaire !!
  2. et à UICollectionViewDelegate, UICollectionViewDataSource
  3. Définissez-les dans viewDidLoad: collectionView.delegate = selfetcollectionView.dataSource = self
  4. Définissez la taille estimée sur Aucune dans le générateur d'interface
  5. Assurez-vous que la méthode suivante a sizeForItemAt et non sizeForItemAtIndexPath

comme:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    return CGSize(width: 100, height:100)
} 
Xys
la source
2
Estimer la taille à Aucune - sauvez ma journée!
Joe Hallenbeck
6

La première classe doit être confirmée à UICollectionViewDelegateFlowLayout. Ensuite, vous devez écrire le code suivant dans viewDidLoad ():

// Pour dire à UICollectionView d'utiliser les méthodes UICollectionViewDelegateFlowLayout de votre UIViewController

collectionView.delegate = self

// Si vous souhaitez définir votre propre disposition de flux de vue de collection

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

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

En utilisant ce code méthode UICollectionViewDelegateFlowLayout

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

sera appelé, vous pouvez définir la taille dans cette méthode.

Progr HS
la source
4

Trois choses que vous devez vérifier si aucune réponse ne fonctionne:

  1. Implémenter le délégué FlowLayout: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Utilisez la méthode pour la taille de l'article pour 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. Sélectionnez Estimate size = Nonedans l'élément Inspect de UICollectionView.

Manish
la source
2

J'ai eu le même problème et rien ne le résoudrait. J'avais un avertissement jaune disant de le rendre privé car il se rapprochait d'une autre fonction définie par le délégué à la mise en page. Ce qui a résolu le problème pour moi était:

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

Notez la différence entre «sizeForItemAtIndexPath» et «sizeForItemAt» correct.

Je me suis arraché les cheveux pendant des jours en essayant de comprendre cela et cela a finalement fonctionné. Ci-dessous, je vais inclure toutes mes fonctions pour vous montrer comment j'ai également "caché" une cellule en rendant la hauteur égale à 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
la source
0

J'ai eu ce problème la nuit dernière. Finalement résolu à minuit quand j'ai réalisé que la méthode 'didSelectItemAtIndex' n'était pas fermée avec un crochet de fermeture "}"

J'ai ajouté un crochet de fermeture tout en bas de la classe à la demande de l'erreur de compilation. Donc, en fait, toutes les méthodes ci-dessous 'didSelectItemAtIndex' étaient à l'intérieur de cette méthode.

Publier ici juste au cas où quelqu'un d'autre gaspillerait 4 heures de ses soirées sur celui-ci :-(

Charlie Seligman
la source
0

Assurez-vous de mettre ceci dans viewDidLoad ()

collectionView.delegate = self
Azam
la source
0

mon problème était que mon objet UICollectionViewDataSource était créé en tant que variable locale. Donc, si vous initialisez votre objet dataSource manuellement dans le code, assurez-vous de le stocker en tant que variable globale.

Petro Darchyn
la source
0

Utilisez cette méthode

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

}

Au lieu de

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

}
Abdul Malik Aman
la source
0

Ajoutez simplement: UICollectionViewDelegateFlowLayout

class YourClass: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {}
Muzammil
la source
-11

Pour moi (dans Swift 3.1), la méthode doit être déclarée publique comme ceci:

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

N'oubliez pas de le rendre public .

Oliver Eichhorn
la source
publicest ce que vous utilisez pour rendre votre code accessible entre les frameworks et les modules.
ScottyBlades