CollectionView sizeForItemAtIndexPath ніколи не викликався


94

Це зводить мене з розуму! У мене є 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) 
    }

Відповіді:


251

Вам потрібно вказати, що ви реалізуєте протокол UICollectionViewDelegateFlowLayoutу своїй декларації класу.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout


10
Я зробив це, але це все ще не називається. :(
Van Du Tran

57

У 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.
Van Du Tran

3
@VanDuTran Не зайвим є стверджувати, що це потрібно, оскільки бути UICollectionViewController не потрібно ...
Майкл Хадсон,

Я думаю, ви мали на увазі, що не збір колекції, Viewcontroller може бути UICollectionViewDelegate.
ScottyBlades

1
UICollectionViewDelegateFlowLayout успадковується від UICollectionViewDelegate, тому просто впроваджуйте UICollectionViewDelegateFlowLayout
evya

46

У мене була та сама проблема. Єдине, що мені допомогло, - це зробити "Приблизний розмір" для розміру комірки під інспектором розміру collectionView "Немає".

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


8
Ти врятував мого дня,
Асіф Алі

1
Якось у всіх інших відповідях на всі інші публікації щодо використання sizeForItemAtпро це не згадувалося. Дуже корисний.
JCutting8

Це божевілля!!!! Я тестував на симуляторі iPhone 5 з версією 10.3.1 iOS і метод викликали. на симуляторі iPhone 5s з методом версії 10.3.1 не викликається !!! Я змінив Розрахунковий розмір на Немає. Його почали телефонувати на iPhone 5s. WT WT WT
Хасан,

Дуже дякую! Моя колекція з користувацькими функціями sizeForItemAtпрацювала добре до Xcode 11.4, коли раптом клітинки мали неправильну ширину. Перепробував купу речей, і це нарешті вдалося.
Філіп

Ти врятував мій Час. Дуже дякую.
Шахбаз Акрам,

15

Стрімкий 3

Щоб встановити розмір комірки UICollectionView, вам потрібно створити та налаштувати об'єкт UICollectionViewFlowLayout. Налаштуйте властивості та встановіть для цього об’єкта макета об’єкт UICollectionView.

Змінюйте висоту комірки та об’єкти 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-

Це не відповідь на те, чому метод делегатів не викликається
Ziv Kesten

12

Стрімкий 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)
} 

2
Оцінити розмір до None - збережіть мій день!
Джо Халленбек,

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: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Використовуйте метод для розміру товару для швидкого 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у Перевірити елемент 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)
    }
}

0

У мене було це питання вчора ввечері. Нарешті вирішив це опівночі, коли я зрозумів, що метод 'didSelectItemAtIndex' не закрився за допомогою закриваючої дужки "}"

На запит про помилку компіляції я додав дужку закриття в самому низу класу. Отже, фактично всі методи нижче "didSelectItemAtIndex" знаходилися всередині цього методу.

Розміщення тут на всякий випадок, якщо хтось інший витратить на це 4 години своїх вечорів :-(


0

Обов’язково поставте це в viewDidLoad ()

collectionView.delegate = self

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 {}

-11

Для мене (у 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.