CollectionView sizeForItemAtIndexPath nigdy nie została wywołana


96

To mnie doprowadza do szału! Mam UICollectionViewController, jak pokazano poniżej:

class PhrasesCompactCollectionViewController: UICollectionViewController

Wywoływane są numberOfSections i cellForItemAt, ale sizeForItemAtIndexPath nigdy nie jest wywoływane. Używam tego samego dokładnego kodu gdzie indziej i działa poprawnie. Używam Xcode 8 Beta 6.

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

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

Odpowiedzi:


255

Musisz określić, że implementujesz protokół UICollectionViewDelegateFlowLayoutw deklaracji klasy.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout


11
Zrobiłem to, ale nadal nie jest to wywołane. :(
Van Du Tran

58

W Swift 3+ Użyj tej metody:

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

Upewnij się, że Twoja klasa jest zgodna zarówno z Delegatem

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout


4
Jest to zbędne, aby zachować zgodność z UICollectionViewDelegateUICollectionViewController.
Van Du Tran

3
@VanDuTran Stwierdzenie, że jest to wymagane, nie jest zbędne, ponieważ bycie kontrolerem UICollectionViewController nie jest wymagane ...
Michael Hudson

Myślę, że miałeś na myśli, że widok inny niż widok kolekcji, Viewcontroller może być UICollectionViewDelegate.
ScottyBlades

1
UICollectionViewDelegateFlowLayout dziedziczą z UICollectionViewDelegate, więc po prostu zaimplementuj UICollectionViewDelegateFlowLayout
evya

48

Miałem ten sam problem. Jedyną rzeczą, która pomogła mi, było ustawienie „Szacowanego rozmiaru” dla rozmiaru komórki w inspektorze rozmiaru collectionView „Brak”.

wprowadź opis obrazu tutaj


9
Uratowałeś mojego dnia kolego, jesteś bohaterem
Asif Ali

1
W jakiś sposób wszystkie inne odpowiedzi we wszystkich innych postach dotyczących używania sizeForItemAtnie wspominały o tym. Bardzo przydatne.
JCutting8

To jest szalone!!!! Testowałem na symulatorze iPhone'a 5 z wersją 10.3.1 iOS i metoda została wywołana. na symulatorze iPhone'a 5s z metodą wersji 10.3.1 nie jest wywoływany !!! Zmieniłem Estimate Size na None. Zaczęło się wywoływać na iPhonie 5s. WT WT WT
hasan

Wielkie dzięki! Mój widok kolekcji z niestandardowym sizeForItemAtdziałał dobrze do Xcode 11.4, kiedy nagle komórki miały niewłaściwą szerokość. Próbowałem wielu rzeczy i to w końcu zadziałało.
Filip

Uratowałeś mój czas. Wielkie dzięki.
Shahbaz Akram

17

Szybki 5

Wszystkie te kroki są wymagane :

  1. Zgodność z UICollectionViewDelegateFlowLayout <== Absolutnie potrzebne !!
  2. i do UICollectionViewDelegate, UICollectionViewDataSource
  3. Ustaw je w viewDidLoad: collectionView.delegate = self icollectionView.dataSource = self
  4. Ustaw Szacowany rozmiar na Brak w Interface Builder
  5. Upewnij się, że następująca metoda ma sizeForItemAt, a nie sizeForItemAtIndexPath

tak jak :

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

3
Oszacuj rozmiar na Brak - oszczędzaj mój dzień!
Joe Hallenbeck

Zaakceptuj tę odpowiedź, jest poprawna!
NickCoder

15

Szybki 3

Aby ustawić rozmiar komórki UICollectionView, musisz utworzyć i dostosować obiekt UICollectionViewFlowLayout . Dostosuj właściwości i ustaw ten obiekt układu na obiekt UICollectionView.

Zmień obiekty cellheight i cell cellWidth zgodnie z wymaganiami (żądana wysokość i szerokość komórki).

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

Upewnij się, że jeśli dodałeś metodę sizeForItemAt indexPath, musisz usunąć tę metodę ...

Usuń poniższą metodę

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

}

12
Jak to jest pomocne?
almas

1
Almas, będzie to pomocne przy ustawianiu niestandardowego rozmiaru komórki UICollectionViewCell ... Istnieją zmienne cellWidth i cellHeight, w których można zdefiniować własne wartości ... Oprócz "layout.sectionInset", "layout.minimumLineSpacing" i "layout .minimumInteritemSpacing ”, te zmienne mają również znaczenie dla rozmiaru UICollectionViewCell ..
Gaurav Rami

2
Działa to tylko wtedy, gdy wszystkie komórki mają ten sam rozmiar. Poniższa odpowiedź jest poprawną odpowiedzią
JeffN

służy to do zmiany rozmiaru UICollectionView, ale nie komórki w widoku
Async

To nie jest odpowiedź na pytanie, dlaczego metoda delegata nie jest wywoływana
Ziv Kesten

6

Pierwsza klasa wymaga potwierdzenia do UICollectionViewDelegateFlowLayout. Następnie musisz napisać następujący kod w viewDidLoad ():

// Aby powiedzieć UICollectionView, aby używał metod UICollectionViewDelegateFlowLayout Twojego UIViewControllera

collectionView.delegate = self

// Jeśli chcesz ustawić własny układ przepływu widoku kolekcji

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

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

Korzystając z tego kodu metody UICollectionViewDelegateFlowLayout

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

zostanie wywołany, możesz ustawić rozmiar w tej metodzie.


4

Trzy rzeczy, które musisz sprawdzić, jeśli żadna odpowiedź nie działa:

  1. Zaimplementuj delegata FlowLayout: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Użyj metody dla rozmiaru przedmiotu dla 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. Wybierz Estimate size = Noneelement Inspect w UICollectionView.


2

Miałem ten sam problem i nic nie mogło go naprawić. Otrzymałem żółte ostrzeżenie, aby uczynić go prywatnym, ponieważ zbliżył się do innej funkcji zdefiniowanej przez delegata układu. Naprawiło to:

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

Zwróć uwagę na różnicę między „sizeForItemAtIndexPath” a poprawnym „sizeForItemAt”.

Wyrywałem sobie włosy przez wiele dni, próbując to rozgryźć i w końcu zadziałało. Poniżej zamieszczę całą moją funkcję, aby pokazać, jak „ukryłem” komórkę, ustawiając wysokość równą 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)
    }
}

1

Upewnij się, że umieściłeś to w viewDidLoad ()

collectionView.delegate = self

0

Miałem ten problem zeszłej nocy. W końcu rozwiązałem to o północy, kiedy zdałem sobie sprawę, że metoda „didSelectItemAtIndex” nie została zamknięta nawiasem zamykającym "}"

Dodałem nawias zamykający na samym dole klasy, gdy pojawiło się pytanie o błąd kompilacji. W efekcie wszystkie poniższe metody „didSelectItemAtIndex” znajdowały się wewnątrz tej metody.

Publikowanie tutaj na wypadek, gdyby ktoś inny marnował na to 4 godziny wieczoru :-(


0

mój problem polegał na tym, że miałem mój obiekt UICollectionViewDataSource utworzony jako zmienna lokalna. Jeśli więc ręcznie inicjalizujesz obiekt dataSource w kodzie, pamiętaj, aby przechowywać go jako zmienną globalną.


0

Użyj tej metody

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

}

Zamiast

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

}

0

Wystarczy dodać: UICollectionViewDelegateFlowLayout

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

-12

Dla mnie (w Swift 3.1) metodę należy zadeklarować publicznie w następujący sposób:

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

Nie zapomnij opublikować tego .


publicjest tym, czego używasz, aby udostępnić kod między strukturami i modułami.
ScottyBlades
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.