CollectionView sizeForItemAtIndexPath никогда не вызывается


96

Это сводит меня с ума! У меня есть UICollectionViewController, как показано ниже:

class PhrasesCompactCollectionViewController: UICollectionViewController

Вызываются numberOfSections и cellForItemAt, но sizeForItemAtIndexPath никогда не вызывается. Я использую точно такой же код в другом месте, и он работает правильно. Я использую Xcode 8 Beta 6.

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

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

Ответы:


255

Вам необходимо указать, что вы реализуете протокол UICollectionViewDelegateFlowLayoutв своем объявлении класса.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout


11
Я сделал это, но он все еще не называется. :(
— Ван Ду Тран

58

В Swift 3+ используйте этот метод:

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

Убедитесь, что ваш класс соответствует требованиям Delegate

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout


4
Это избыточно для соблюдения, UICollectionViewDelegateкак это уже делает UICollectionViewController.
— Ван Дю Тран,

3
@VanDuTran Не лишним будет сказать, что это необходимо, потому что быть UICollectionViewController не требуется ...
— Майкл Хадсон,

Я думаю, вы имели в виду, что Viewcontroller не является представлением коллекции, может быть UICollectionViewDelegate.
— ScottyBlades

1
UICollectionViewDelegateFlowLayout наследуется от UICollectionViewDelegate, поэтому просто реализуйте UICollectionViewDelegateFlowLayout
— evya

49

У меня такая же проблема. Единственное, что мне помогло, - это установить «Расчетный размер» для размера ячейки в инспекторе размера коллекции «Нет».

введите описание изображения здесь


9
Ты спас мне день, приятель, ты герой
— Асиф Али

1
Как-то все другие ответы на все другие сообщения об использовании sizeForItemAtне упоминали об этом. Очень полезно.
— JCutting8,

Это безумие!!!! Я тестировал симулятор iPhone 5 с версией iOS 10.3.1, и метод был вызван. на iPhone 5s симулятор с версией 10.3.1 метод не вызывается !!! Я изменил расчетный размер на «Нет». Его начали называть на iPhone 5s. WT WT WT
— хасан

Большое спасибо! Моя коллекция с пользовательскими настройками sizeForItemAtработала хорошо до Xcode 11.4, когда внезапно ячейки оказались неправильной ширины. Пробовал кучу вещей, и это, наконец, сработало.
— Филип

Вы сэкономили мне время. Большое спасибо.
— Шахбаз Акрам

17

Swift 5

Все эти шаги обязательны :

  1. Соответствует UICollectionViewDelegateFlowLayout <== Абсолютно необходимо !!
  2. и чтобы UICollectionViewDelegate, UICollectionViewDataSource
  3. Установите их в viewDidLoad: collectionView.delegate = selfиcollectionView.dataSource = self
  4. Установите для размера оценки значение None в Interface Builder
  5. Убедитесь, что следующий метод имеет sizeForItemAt, а не sizeForItemAtIndexPath

в качестве :

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

3
Оценить размер до «Нет» - спаси день!
— Джо Халленбек,

Примите этот ответ, он правильный!
— NickCoder

15

Swift 3

Чтобы установить размер ячейки UICollectionView, вам необходимо создать и настроить объект UICollectionViewFlowLayout. Настройте свойства и установите этот объект макета в объект UICollectionView.

Измените ячейки cellheight и cellWidth в соответствии с вашими требованиями (желаемую высоту и ширину ячейки).

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

Убедитесь, что если вы добавили метод sizeForItemAt indexPath, тогда необходимо УДАЛИТЬ метод ...

Удалить ниже метод

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

}

12
Чем это полезно?
— almas

1
Алмас, Это будет полезно для установки пользовательского размера ячейки UICollectionViewCell ... Существуют переменные cellWidth и cellHeight, в которых вы можете определять свои собственные значения ... А также "layout.sectionInset", "layout.minimumLineSpacing" и "layout .minimumInteritemSpacing ", эти переменные также имеют значение для размера UICollectionViewCell ..
— Горав Рами,

2
Это работает, только если все ячейки одинакового размера. Правильный ответ приведен ниже
— JeffN

это для изменения размера UICollectionView, но не ячейки внутри представления
— Async

Это не ответ на вопрос, почему не вызывается метод делегата
— Зив Кестен

6

Первому классу необходимо подтвердить UICollectionViewDelegateFlowLayout. Затем вам нужно написать следующий код в viewDidLoad ():

// Чтобы указать UICollectionView использовать методы UICollectionViewDelegateFlowLayout вашего UIViewController

collectionView.delegate = self

// Если вы хотите установить свой собственный макет потока представления коллекции

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

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

Используя этот метод кода UICollectionViewDelegateFlowLayout

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

будет вызван, вы можете установить размер в этом методе.


4

Если нет ответа, вам нужно проверить три вещи:

  1. Реализуйте FlowLayout Delegate: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Используйте метод размера элемента для 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. Выберите Estimate size = Noneв Inspect элемент UICollectionView.


2

У меня была такая же проблема, и ничто не могло ее исправить. У меня было желтое предупреждение о том, что нужно сделать его закрытым, потому что оно близко к другой функции, определенной делегатом макета. Для меня это было исправлено:

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

Обратите внимание на разницу между sizeForItemAtIndexPath и sizeForItemAt.

Я вырывал себе волосы в течение нескольких дней, пытаясь понять это, и, наконец, это сработало. Ниже я включу все свои функции, чтобы показать вам, как я также «спрятал» ячейку, сделав высоту равной 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

Убедитесь, что вы поместили это в viewDidLoad ()

collectionView.delegate = self

0

У меня была эта проблема вчера вечером. В конце концов решил это в полночь, когда я понял, что метод didSelectItemAtIndex не был закрыт закрывающей скобкой "}"

Я добавил закрывающую скобку в самом низу класса, когда ее спросила ошибка компиляции. Таким образом, все методы, указанные ниже, «didSelectItemAtIndex» были внутри этого метода.

Публикация здесь на случай, если кто-то еще потратит на это 4 часа своих вечеров :-(


0

Моя проблема заключалась в том, что у меня был объект UICollectionViewDataSource, созданный как локальная переменная. Поэтому, если вы инициализируете свой объект dataSource вручную в коде, обязательно сохраните его как глобальную переменную.


0

Используйте этот метод

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

}

Вместо того

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

}

0

Просто добавьте: UICollectionViewDelegateFlowLayout

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

-12

Для меня (в Swift 3.1) метод должен быть объявлен публичным следующим образом:

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

Не забудьте сделать это общедоступным .


publicэто то, что вы используете, чтобы сделать свой код доступным между фреймворками и модулями.
— ScottyBlades
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.