Метод UICollectionReusableView не викликається


79

Я хочу, щоб мої розділи в UICollectionViewмали заголовок із зображенням.

Я виконав ці кроки:

  • на раскадровці, призначив заголовок як аксесуар для мого UICollectionView
  • дав йому ідентифікатор
  • створив підклас UICollectionReusableViewдля нього
  • призначив користувацький клас класу на розкадруванні.
  • покладіть ImageViewу заголовку аксесуар
  • зробив вихід для ImageViewспеціального класу у .hфайлі
  • Реалізовано наступне на viewDidLoad:

 

[self.collectionView registerClass:[ScheduleHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerIdentifier];

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *reusableview = nil;

    if (kind == UICollectionElementKindSectionHeader)
    {
        ScheduleHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerIdentifier forIndexPath:indexPath];

        headerView.headerImageView.image = [UIImage imageNamed:@"blah.png"];

        reusableview = headerView;
    }

    return reusableview;
}

Я знаю, що методи джерела даних та делегатів працюють, оскільки я бачу всі комірки та його розділи. Однак у мене немає своїх заголовків. Я вказав точку зупинки за вищенаведеним методом, і його ніколи не викликають.

Що я роблю не так?


3
Зверніть увагу, що ви порівнюєте вказівники на рядки kind == UICollectionElementKindSectionHeaderзамість вмісту рядків, напевно, ви хочете використовувати їх [kind isEqualToString: UICollectionElementKindSectionHeader].
Mac_Cain13

Відповіді:


200

Здається, вам потрібно надати заголовку ненульовий розмір або collectionView:viewForSupplementaryElementOfKind:atIndexPathйого не викликають. Тож або встановіть headerReferenceSizeвластивість макета потоку так:

flowLayout.headerReferenceSize = CGSizeMake(self.collectionView.frame.size.width, 100.f);

Свіфт 5+

flowLayout.headerReferenceSize = CGSize(CGSize(width: self.collectionView.frame.size.width, height: 100))

або застосуйте, collectionView:layout:referenceSizeForHeaderInSectionякщо ви хочете змінювати розмір за розділами.


1
у поданні колекції, чи можу я зробити для динамічної висоти за допомогою авторозкладки замість визначення розміру headerReference?
Khant Thu Linn

чи можна встановити headerReferenceSize у розкадруванні на flowLayout?
Радек Вільчак

1
Так, це спрацювало! layout.headerReferenceSize = CGSize (ширина: (self.collectionView? .frame.width)!, висота: 50); for swift4
Antony Ouseph

headerReferenceSizeпрацює, але мені потрібні різні розміри для різних розділів. А метод, який ви вказали, взагалі не викликається
Вячаслав Герчиков

33

Ви відповіли на запитання, але словами я краще розумію:

Щоб зробити викликаний метод, додайте такі методи:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {
    return CGSizeMake(60.0f, 30.0f);
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section {
    return CGSizeMake(60.0f, 30.0f);
}

... і йти звідти.


31

Swift 4 Xcode 9.1 Beta 2

Додайте @objc

@objc func collectionView(_ collectionView: UICollectionView, layout  collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize{
    let size = CGSize(width: 400, height: 50)
    return size
}

Подяки: https://medium.com/@zonble/your-delegation-methods-might-not-be-called-in-swift-3-c6065ed7b4cd


Дякую! Врятував мій недопалок. До речі, я помітив, що ця функція не відображається у списку автозаповнення для collectionViewDelegate. Не знаю чому, такий дивний. Також дивно, що нам потрібен тег @objc перед ним.
C0D3

3
У мене працювало лише додавання @objc до функції в Swift 4. Смішно.
Луїс Кремен,

7
Відповідність UICollectionViewDelegateFlowLayout замість UICollectionViewDelegate також виправляє це без @objc, якщо ви використовуєте UICollectionViewFlowLayout.
nemissm

набагато краще, якщо ви використовуєте межі collectionView, щоб встановити заголовок / колонтитул вашого розділу: let size = CGSize (collectionView.bounds.width, height: 50)
omaestra

18

Ви додали UICollectionViewDelegateFlowLayout до поточного інтерфейсу? Це спрацювало для мене.

@interface MyViewController () <UICollectionViewDelegateFlowLayout>

Стрімкий:

class MyViewController: UICollectionViewDelegateFlowLayout {


1
Ага! так це ...UICollectionViewDelegateFlowLayout
Аян Сенгупта

8

Swift 3.0 (xcode 8.2.1)

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    return CGSize(width:collectionView.frame.size.width, height:30.0)
}

5

Існує швидка версія:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    let size = CGSize(width: 400, height: 50)
    return size
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
    let size = CGSize(width: 400, height: 50)
    return size
}

XCode (версія 7.3.1) не пропонує ці методи автозавершення!

Якщо ви просто хочете заголовок, просто залиште метод заголовка.


3
    @objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { }

Наведений вище код працював для мене


2

Моя проблема полягала в тому, що в swift 3 ім'я функції viewForSupplementaryElementOfKind дещо змінилося порівняно з усіма повідомленнями, які переповнювали стек. Отже, його ніколи не дзвонили. Переконайтеся, що якщо ви знаходитесь у швидкій версії 3, ви відповідаєте функції делегування:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {}

Мій також. Для мене не було "_", "atIndexPath" замість "at" та "NSIndexPath" замість "IndexPath"; оскільки я десь скопіював метод, і IDE не видав мені помилки.
Ашкан Сарлак

1

У мене те саме питання. Я додав, referenceSizeForFooterInSectionале потім також viewForSupplementaryElementOfKindне телефоную. Я додав цей код, viewDidLoad()і він працював для мене:

if let flowLayout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
    flowLayout.sectionFootersPinToVisibleBounds = true   
}

0

Для мене в Swift 4.2 функція collectionView (collectionView: kind: indexPath :) -> UICollectionReusableView ніколи не викликалася. Це було для подання колекції в UIViewController. Я помітив, що існуючі функції подання колекції були кваліфіковані за допомогою @objc, і що UICollectionView не прийняв протоколи UICollectionViewDataSource та UICollectionViewDelegate. Як тільки я прийняв протоколи, я отримав помилки, що функції подання колекції не відповідали протоколу. Я виправив синтаксис функції, видалив кваліфікатори, і заголовки розділів почали працювати.


0

Якщо у вас є загальний підклас, то ви повинні подбати про те, щоб вказати ім'я методу делегування ObjC, якщо воно відрізняється від імені Swift ( https://bugs.swift.org/browse/SR-2817 ).

@objc (collectionView:viewForSupplementaryElementOfKind:atIndexPath:)
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.