UICollectionView Несколько разделов и заголовков

Я пытаюсь сделать несколько разделов в моем представлении коллекции с заголовком для каждого раздела. Я не знаю Obj-C, и я нашел для него много учебников, но не смог понять, как преобразовать его в Swift.

Все мои данные являются статическими, поэтому мне нужен только какой-то массив или словарь, который я могу использовать для создания нескольких разделов. У меня уже есть представление коллекции с 1 секцией, поэтому, если у вас есть понимание или код для нескольких разделов, которые будут полезны.

Я знаю, как установить несколько разделов с помощью

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int   {
    return sectionData.count
}

Я думаю, что главное, что мне нужно, это реализовать эту функцию

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { }

и настройки данных!

UICollectionView и UITableView почти одинаковы, поэтому, если вы знаете, как делать несколько разделов в UITableView в Swift, ваша помощь также оценивается

Ответ 1

Функция cellForItemAtIndexPath обрабатывает каждую секцию с помощью ячеек, она не обрабатывает разделы или дополнительные элементы управления, и, следовательно, это не главное, что вам нужно, когда речь заходит о создании заголовков разделов.

метод, который вам нужно реализовать, viewForSupplementaryElementOfKind. Его подпись:

func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {}

Предполагая, что ваш CollectionView работает правильно для 1 раздела (вы правильно заполнили тело cellForItemAtIndexPath, и ваш массив sectionData правильно отражает количество разделов, которые вы хотите отобразить), вы должны иметь возможность создавать заголовки секций, используя следующие указатели:

Наряду с ячейками UICollectionView также поддерживает "дополнительные" объекты вида, обычно используемые для верхних или нижних колонтитулов. Эти дополнительные представления действуют очень похоже на объекты UICollectionViewCell. Точно так же, как cellForItemAtIndexPath обрабатывает ячейки, функция viewForSupplementaryElementOfKind обрабатывает дополнительные представления.

Чтобы реализовать это, вам нужно сначала подготовить свой ViewController для этого. Сначала отредактируйте свой объект макета, чтобы отобразить соответствующий размер заголовка, который каждый заголовок будет придерживаться:

 let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
 layout.headerReferenceSize = CGSize(width: self.view.frame.size.width, height: 30)

ПРИМЕЧАНИЕ. Я использую UICollectionViewFlowLayout

Затем, если вы еще этого не сделали, создайте класс SectionHeader, который определяет объект заголовка каждого раздела, поэтому вы можете затем зарегистрировать этот класс с помощью объекта collectionView следующим образом:

  collectionView!.registerClass(SectionHeaderView.self, forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "SectionHeaderView");

Здесь первый и третий приведенные аргументы совпадают с регистрацией класса UICollectionViewCell, первым аргументом в этом методе является ссылка на класс заголовка раздела, который вы создали. Третий - это идентификатор повторного использования для дополнительного просмотра.

Второй аргумент специфичен для дополнительных представлений, это задает вид дополнительного вида, который в этом случае является заголовком, для него используется константная строка, предоставленная классом UICollectionViewFlowLayout UICollectionElementKindSectionHeader. Если вы заметили параметры в viewForSupplementaryElementOfKind, этот вид позже передается как параметр kind: String.

Заполните тело вашего viewForSupplementaryElementOfKind так же, как и для функции cellForItemAtIndexPath. Используя метод dequeueReusableSupplementaryViewOfKind для создания объекта SectionHeader, затем установите необходимые атрибуты (метки, цвета и т.д.) и наконец, вернуть объект заголовка.

Надеюсь, это поможет!

Ориентир:

https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UICollectionViewDataSource_protocol/index.html#//apple_ref/occ/intfm/UICollectionViewDataSource/

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionViewFlowLayout_class/index.html#//apple_ref/c/data/UICollectionElementKindSectionHeade

Ответ 2

Вот код, который работал у меня

создать ячейку заголовка. Чтобы сделать то, что я создал пользовательский класс ячейки и наконечник, чтобы выполнить настройку ячейки в графическом редакторе

В viewDidLoad добавьте следующие

self.collectionView?.registerNib(UINib(nibName: "KlosetCollectionHeaderViewCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderCell")

Затем вы добавляете функцию делегата

override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> KlosetCollectionHeaderViewCell {

    let headerCell = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "HeaderCell", forIndexPath: indexPath) as? KlosetCollectionHeaderViewCell    

    return headerCell!
  }

Это поместит HeaderCell в SectionView из PFCollectionView Элементы управления, которые отображаются в ячейке, которую вы добавляете в файл xib, а также выходы и действия

Ответ 3

После создания и регистрации пользовательских заголовков (и/или нижних колонтитулов) вы можете легко указать разные заголовки (или, тем не менее, нижеследующие) для разных разделов. Вот пример:

    override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        switch kind {
        case UICollectionElementKindSectionHeader:
            let section = indexPath.section

            switch section {
            case 0:
                let userHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: homeHeaderReuseIdentifier, for: indexPath) as! UserHeader
                return userHeader
            default:
                let postHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: sectionSpacingHeaderReuseIdentifier, for: indexPath) as! PostHeader
                return postHeader
            }
        case UICollectionElementKindSectionFooter:
            let userFooter = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: homeFooterReuseIdentifier, for: indexPath) as! UserFooter
            return userFooter
        default:
            return UICollectionReusableView()
        }
    }

Обязательно укажите правильное количество разделов:

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }

Ответ 4

Готовое решение для Swift-3

i) Создать пользовательскую ячейку && соответствующий xib

   class SectionHeaderView: UICollectionViewCell {
        static let kReuseIdentifier = "SectionHeaderView"
        @IBOutlet weak var invitationsSectionHeader: UILabel!
        @IBOutlet weak var numberOfPerson: UILabel!
 }

ii) Регистрация ячейки коллекции пользовательской коллекции для HeaderView

 self.collectionView.register(UINib(nibName: SectionHeaderView.kReuseIdentifier, bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: SectionHeaderView.kReuseIdentifier)

iii) Вызовите функцию делегата для визуализации представления пользовательского заголовка.

  func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        switch kind {
        case UICollectionElementKindSectionHeader:
           let  headerView: SectionHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: SectionHeaderView.kReuseIdentifier, for: indexPath) as! SectionHeaderView
            return headerView
        default:
            return UICollectionReusableView()
        }
    }

iv) Упоминание высоты пользовательского представления заголовка

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

Ответ 5

Определите свой UICollectionViewCell, который будет вашим видом заголовка вида UICollectionElementKindSectionHeader. В моем случае у меня есть два заголовка: OfferHeaderCell и APRHeaderCell, как указано ниже:

verticalCollectionView.register(UINib(nibName: "OfferHeaderCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "OfferHeaderCell")
verticalCollectionView.register(UINib(nibName: "APRHeaderCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "APRHeaderCell")

Идем дальше и возвращаем заголовок для каждого раздела, а затем устанавливаем размер заголовка раздела, чтобы иметь нулевой размер в этой функции UICollectionViewDelegateFlowLayout

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    if(section==0) {
        return CGSize.zero
    } else if (section==1) {
        return CGSize(width:collectionView.frame.size.width, height:133)
    } else {
        return CGSize(width:collectionView.frame.size.width, height:100)
    }

}

Важно определить viewForSupplementaryElementOfKind для двух разных разделов, как показано ниже:

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

    var reusableview = UICollectionReusableView()
    if (kind == UICollectionElementKindSectionHeader) {
        let section = indexPath.section
        switch (section) {
        case 1:
            let  firstheader: OfferHeaderCell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "OfferHeaderCell", for: indexPath) as! OfferHeaderCell
            reusableview = firstheader
        case 2:
            let  secondHeader: APRHeaderCell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "APRHeaderCell", for: indexPath) as! APRHeaderCell
            reusableview = secondHeader
        default:
            return reusableview

        }
    }
    return reusableview
}

И, наконец, Datasource,

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 3
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    if (section==2) {
        return 2
    }
    return 0
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = verticalCollectionView.dequeueReusableCell(withReuseIdentifier: "ReviseOfferCell", for: indexPath)
    cell.backgroundColor = UIColor.white
    return cell
}

Примечание. Не забудьте добавить UICollectionFlowLayout, как показано ниже:

//MARK: UICollectionViewDelegateFlowLayout

extension MakeAnOfferController: UICollectionViewDelegateFlowLayout {

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

            if indexPath.item == 0 {
                return CGSize(width: self.view.frame.size.width, height: 626.0)
            }
            return CGSize()
        }

        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {

            if(section==0) {
                return CGSize.zero
            } else if (section==1) {
                return CGSize(width:collectionView.frame.size.width, height:133)
            } else {
                return CGSize(width:collectionView.frame.size.width, height:100)
            }
        }
    }