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.